@prampta/sdk 0.3.2 → 0.7.0
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/LICENSE +202 -0
- package/README.md +286 -204
- package/dist/index.d.mts +615 -0
- package/dist/index.d.ts +615 -3
- package/dist/index.js +1322 -2
- package/dist/index.mjs +1266 -0
- package/package.json +35 -46
- package/dist/client.d.ts +0 -75
- package/dist/client.d.ts.map +0 -1
- package/dist/client.js +0 -221
- package/dist/client.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/mcp.d.ts +0 -3
- package/dist/mcp.d.ts.map +0 -1
- package/dist/mcp.js +0 -324
- package/dist/mcp.js.map +0 -1
- package/dist/types.d.ts +0 -60
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -2
- package/dist/types.js.map +0 -1
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,615 @@
|
|
|
1
|
+
import { Directory } from '@pregen/verify';
|
|
2
|
+
export { Directory as PregenDirectory, loadDirectory as loadPregenDirectory } from '@pregen/verify';
|
|
3
|
+
|
|
4
|
+
/** PRE-GEN v5 serialization. Do not silently replace it with JCS: existing
|
|
5
|
+
* signatures use these bytes. A new canonicalization needs a new version. */
|
|
6
|
+
declare function canonicalJson(obj: unknown): string;
|
|
7
|
+
|
|
8
|
+
declare class RegistryDirectoryError extends Error {
|
|
9
|
+
constructor(message: string);
|
|
10
|
+
}
|
|
11
|
+
interface RegistryDirectoryOptions {
|
|
12
|
+
/** Trust anchor obtained independently, NOT from the directory itself. */
|
|
13
|
+
stewardPublicKeyHex: string;
|
|
14
|
+
/** Highest accepted sequence, persisted by the application across restarts. */
|
|
15
|
+
minSequence?: number;
|
|
16
|
+
/** Last accepted state from durable storage; detects same-sequence forks. */
|
|
17
|
+
previousSnapshot?: {
|
|
18
|
+
sequence: number;
|
|
19
|
+
hash: string;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/** Immutable, signature-verified directory snapshot. No network discovery,
|
|
23
|
+
* automatic root replacement, registry accreditation or rights attestation. */
|
|
24
|
+
declare class TrustedRegistryDirectory {
|
|
25
|
+
#private;
|
|
26
|
+
readonly sequence: number;
|
|
27
|
+
readonly snapshotHash: string;
|
|
28
|
+
private constructor();
|
|
29
|
+
static verify(input: unknown, options: RegistryDirectoryOptions): Promise<TrustedRegistryDirectory>;
|
|
30
|
+
private registryFor;
|
|
31
|
+
/** V-11: checked before forwarding a provider's credential to an endpoint. */
|
|
32
|
+
assertEndpoint(subject: string, baseUrl: string): void;
|
|
33
|
+
/** V-10: use only AFTER independently verifying the object's signature. */
|
|
34
|
+
assertSigner(code: string, keyId: string): void;
|
|
35
|
+
assertDecision(subject: string, license: string | null, keyId: string, baseUrl: string): void;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
interface LicenseSignatureInput {
|
|
39
|
+
body: Record<string, unknown>;
|
|
40
|
+
licenseId: string;
|
|
41
|
+
subjectPublicKeyHex: string;
|
|
42
|
+
subjectSignatureHex: string;
|
|
43
|
+
operatorPublicKeyHex: string;
|
|
44
|
+
operatorSignatureHex: string;
|
|
45
|
+
}
|
|
46
|
+
/** V-9 crypto check only. Obtain keys independently and check namespace,
|
|
47
|
+
* authority, status and scope separately; true is NOT a proof of consent. */
|
|
48
|
+
declare function verifyLicenseSignatures(input: LicenseSignatureInput): Promise<{
|
|
49
|
+
subjectValid: boolean;
|
|
50
|
+
operatorValid: boolean;
|
|
51
|
+
}>;
|
|
52
|
+
|
|
53
|
+
/** Connect Step 1. Server-side only; reporting NEVER authorizes generation. */
|
|
54
|
+
interface Observation {
|
|
55
|
+
schema_version: "pg.observation.v1";
|
|
56
|
+
event_id: string;
|
|
57
|
+
output_id: string;
|
|
58
|
+
subject_id: string;
|
|
59
|
+
event_type: "output.created" | "output.modified" | "output.published" | "publication.removed";
|
|
60
|
+
output_hash: string;
|
|
61
|
+
occurred_at: string;
|
|
62
|
+
declared_purpose: "personal" | "commercial" | "educational" | "research" | "editorial" | "unknown";
|
|
63
|
+
parent_output_hash?: string;
|
|
64
|
+
publication_url?: string;
|
|
65
|
+
}
|
|
66
|
+
interface ReportInput {
|
|
67
|
+
/** Stable provider job/event key. Different publications/edits need different keys. */
|
|
68
|
+
eventKey: string;
|
|
69
|
+
outputId: string;
|
|
70
|
+
/** Provider-confirmed association, NOT automatically a text matcher hit. */
|
|
71
|
+
subjectId: string;
|
|
72
|
+
/** Original event time, retained across retries. */
|
|
73
|
+
occurredAt: string;
|
|
74
|
+
eventType?: Observation["event_type"];
|
|
75
|
+
purpose?: Observation["declared_purpose"];
|
|
76
|
+
/** Actual output bytes or text, never a URL to be downloaded. Stays local. */
|
|
77
|
+
output?: Uint8Array | string;
|
|
78
|
+
/** For large files, compute incrementally in your storage pipeline. */
|
|
79
|
+
outputHash?: string;
|
|
80
|
+
parentOutputHash?: string;
|
|
81
|
+
publicationUrl?: string;
|
|
82
|
+
}
|
|
83
|
+
interface ObservationOutbox {
|
|
84
|
+
/** Persist atomically under event_id; same payload is a no-op, changed payload
|
|
85
|
+
* must reject. Namespace storage by provider AND environment. Resolve only
|
|
86
|
+
* after durable commit. Implement using the provider's existing DB/job queue. */
|
|
87
|
+
put(event: Observation): Promise<void>;
|
|
88
|
+
}
|
|
89
|
+
type DeliveryResult = {
|
|
90
|
+
status: "accepted";
|
|
91
|
+
observationId: string;
|
|
92
|
+
} | {
|
|
93
|
+
status: "retry";
|
|
94
|
+
httpStatus?: number;
|
|
95
|
+
retryAfterMs: number;
|
|
96
|
+
} | {
|
|
97
|
+
status: "rejected";
|
|
98
|
+
httpStatus: number;
|
|
99
|
+
};
|
|
100
|
+
declare class PramptaReporter {
|
|
101
|
+
private readonly config;
|
|
102
|
+
private readonly baseUrl;
|
|
103
|
+
private readonly timeoutMs;
|
|
104
|
+
constructor(config: {
|
|
105
|
+
baseUrl: string;
|
|
106
|
+
providerId: string;
|
|
107
|
+
token: string;
|
|
108
|
+
outbox: ObservationOutbox;
|
|
109
|
+
timeoutMs?: number;
|
|
110
|
+
});
|
|
111
|
+
/** No PRAMPTA network call: hash locally and commit to the durable outbox.
|
|
112
|
+
* A storage failure is surfaced, never reported as success. Run from the
|
|
113
|
+
* provider's generation-completed job, not as an authorization gate. */
|
|
114
|
+
report(input: ReportInput): Promise<{
|
|
115
|
+
status: "queued";
|
|
116
|
+
eventId: string;
|
|
117
|
+
}>;
|
|
118
|
+
/** One bounded attempt by your queue worker. Keep/retry on `retry`, quarantine
|
|
119
|
+
* on `rejected`, acknowledge only `accepted`. Never changes /verify behavior. */
|
|
120
|
+
deliver(event: Observation): Promise<DeliveryResult>;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* PRAMPTA SDK for TypeScript / Node.js
|
|
125
|
+
*
|
|
126
|
+
* Pre-generation authorization for AI content.
|
|
127
|
+
* Verifies operator Ed25519 signatures on decisions — not a blind HTTP wrapper.
|
|
128
|
+
*
|
|
129
|
+
* @example Basic verification
|
|
130
|
+
* ```ts
|
|
131
|
+
* import { Prampta } from "@prampta/sdk";
|
|
132
|
+
*
|
|
133
|
+
* const pg = new Prampta({
|
|
134
|
+
* baseUrl: "https://api2.prampta.com",
|
|
135
|
+
* providerId: "my-ai-service",
|
|
136
|
+
* licenseeId: "lic-sandbox", // synthetic sandbox fixture only
|
|
137
|
+
* // Your runtime credential's `exchange_secret` — from your provider
|
|
138
|
+
* // application's verify-email/verify-domain response (see the Provider
|
|
139
|
+
* // Connect Guide). NOT the legacy shared pair token; see `token` below.
|
|
140
|
+
* token: process.env.PRAMPTA_TOKEN,
|
|
141
|
+
* });
|
|
142
|
+
*
|
|
143
|
+
* // Throws if denied — fail-closed by default
|
|
144
|
+
* await pg.assertAllowed("sbx-allowed", {
|
|
145
|
+
* prompt: "A sandbox portrait",
|
|
146
|
+
* modality: "image",
|
|
147
|
+
* model: "your-model",
|
|
148
|
+
* intendedUse: { useCase: "research" },
|
|
149
|
+
* });
|
|
150
|
+
* ```
|
|
151
|
+
*/
|
|
152
|
+
|
|
153
|
+
interface PramptaConfig {
|
|
154
|
+
/** The PRAMPTA registry URL. Falls back to PRAMPTA_BASE_URL env var. */
|
|
155
|
+
baseUrl?: string;
|
|
156
|
+
/** Your provider ID. Falls back to PRAMPTA_PROVIDER_ID env var. */
|
|
157
|
+
providerId?: string;
|
|
158
|
+
/** The licensee ID (`prampta_licensee_id` from Connect AI). Falls back to
|
|
159
|
+
* PRAMPTA_LICENSEE_ID. Optional: without it, verify is a provider-level
|
|
160
|
+
* check that can only answer `not_blocked` for `useCase: "personal"`. */
|
|
161
|
+
licenseeId?: string;
|
|
162
|
+
/**
|
|
163
|
+
* The runtime bearer credential. This is your `ProviderCredential`'s
|
|
164
|
+
* `exchange_secret` — issued inline by `verify-email` (sandbox) or
|
|
165
|
+
* `verify-domain/confirm` (production) during provider onboarding.
|
|
166
|
+
* The `prampta_connection_token` returned by Connect AI is NOT accepted
|
|
167
|
+
* for production runtime calls.
|
|
168
|
+
* Falls back to PRAMPTA_TOKEN env var.
|
|
169
|
+
*
|
|
170
|
+
* The legacy shared PAIR TOKEN also works here ONLY while the server is
|
|
171
|
+
* running in `PILOT_MODE` (pre-migration deployments) — production
|
|
172
|
+
* deployments with the trust flags on (the v1.0.0 default) reject it with
|
|
173
|
+
* `PG_NO_PAIR`. Do not build new integrations against the pair token; it
|
|
174
|
+
* exists solely so an already-connected provider keeps working during
|
|
175
|
+
* migration. See docs/PRAMPTA-Provider-Connect-Guide-2026-08.md.
|
|
176
|
+
*/
|
|
177
|
+
token?: string;
|
|
178
|
+
/** Request timeout in milliseconds (default 3000). */
|
|
179
|
+
timeoutMs?: number;
|
|
180
|
+
/**
|
|
181
|
+
* Max retry attempts for transient failures (network errors, timeouts,
|
|
182
|
+
* HTTP 429, and 5xx). Default 2 (so up to 3 total attempts). Set 0 to disable.
|
|
183
|
+
* Retries use exponential backoff. Non-transient errors (4xx other than 429,
|
|
184
|
+
* refusals, signature/schema errors) are never retried.
|
|
185
|
+
*/
|
|
186
|
+
maxRetries?: number;
|
|
187
|
+
/** Base backoff in ms between retries; doubles each attempt. Default 200. */
|
|
188
|
+
retryBackoffMs?: number;
|
|
189
|
+
/** If true (default), deny on backend errors/timeouts. */
|
|
190
|
+
failClosed?: boolean;
|
|
191
|
+
/**
|
|
192
|
+
* Pinned operator public key(s), hex — the trust anchor for signature
|
|
193
|
+
* verification. Obtain out of band (PRAMPTA docs), not from the API that
|
|
194
|
+
* serves decisions. Pass one, or several (comma/space separated) to pin the
|
|
195
|
+
* current + next key and rotate with zero downtime. Falls back to
|
|
196
|
+
* PRAMPTA_OPERATOR_PUBLIC_KEY. If omitted, verification runs in
|
|
197
|
+
* trust-on-first-use mode (a warning is emitted) — do not do this in prod.
|
|
198
|
+
*/
|
|
199
|
+
operatorPublicKeyHex?: string;
|
|
200
|
+
/**
|
|
201
|
+
* Monitor mode: when false, refusals do NOT block generation — the SDK still
|
|
202
|
+
* verifies and records a signed decision, but assertAllowed / withAuthorization
|
|
203
|
+
* proceed instead of throwing. Use for a pilot rollout. Default true.
|
|
204
|
+
*/
|
|
205
|
+
enforce?: boolean;
|
|
206
|
+
/**
|
|
207
|
+
* If true (default), verify operator signature on every decision.
|
|
208
|
+
* Set to false ONLY for local development — never in production.
|
|
209
|
+
*/
|
|
210
|
+
verifyDecisionSignature?: boolean;
|
|
211
|
+
/**
|
|
212
|
+
* If true, verify() throws PramptaSchemaError LOCALLY — before any network
|
|
213
|
+
* call — when neither providerUserId nor providerIdentityLinkId was
|
|
214
|
+
* supplied. Off by default (most integrations have legitimately unbound
|
|
215
|
+
* calls); turn it on once your integration always acts for a specific end
|
|
216
|
+
* user, so a caller that forgot to pass one fails fast and loud in your own
|
|
217
|
+
* code rather than silently reaching the server as an "unbound" request.
|
|
218
|
+
* Independent of, and a cheaper backstop for, the server-side
|
|
219
|
+
* REQUIRE_PROVIDER_USER_BINDING enforcement — this catches the mistake
|
|
220
|
+
* before spending a round-trip. Default false.
|
|
221
|
+
*/
|
|
222
|
+
requireUserBinding?: boolean;
|
|
223
|
+
/** Out-of-band verified namespace directory. Opt-in while the public
|
|
224
|
+
* steward root is not yet published. Requires pinned operator keys. */
|
|
225
|
+
registryDirectory?: TrustedRegistryDirectory;
|
|
226
|
+
/** The PRE-GEN directory from `loadPregenDirectory()`, with the steward key built in.
|
|
227
|
+
* Before a request the SDK checks that `baseUrl` owns the subject's namespace; on an
|
|
228
|
+
* `allow` it also runs @pregen/verify `checkDecision`: the signing key must be one the
|
|
229
|
+
* directory lists for the license's namespace (origin keys pinned), on top of the checks
|
|
230
|
+
* below. Recommended over `registryDirectory`. */
|
|
231
|
+
pregenDirectory?: Directory;
|
|
232
|
+
}
|
|
233
|
+
interface VerifyRequest {
|
|
234
|
+
/** Subject to verify authorization for. */
|
|
235
|
+
subjectId: string;
|
|
236
|
+
/** Raw prompt text — will be hashed, never sent to PRAMPTA. */
|
|
237
|
+
prompt?: string;
|
|
238
|
+
/** Pre-computed SHA-256 hash. Use instead of prompt if you've already hashed. */
|
|
239
|
+
promptHash?: string;
|
|
240
|
+
/** Generation modality: "image", "video", "audio", "text", "3d". */
|
|
241
|
+
modality?: string;
|
|
242
|
+
/** The AI model being used. */
|
|
243
|
+
model?: string;
|
|
244
|
+
/** Intended use metadata. */
|
|
245
|
+
intendedUse?: {
|
|
246
|
+
channel?: string;
|
|
247
|
+
productName?: string;
|
|
248
|
+
projectName?: string;
|
|
249
|
+
categories?: string[];
|
|
250
|
+
territory?: string;
|
|
251
|
+
/** Commercial-model campaign binding — required by premium billing terms. */
|
|
252
|
+
campaignId?: string;
|
|
253
|
+
/** The use-case tier: "personal" | "educational" | "research" |
|
|
254
|
+
* "editorial" | "commercial". Personal use with no licence answers
|
|
255
|
+
* disposition "not_blocked" only when this is declared (NMP Q13). */
|
|
256
|
+
useCase?: string;
|
|
257
|
+
/** Rights requested in addition to the generation modality. */
|
|
258
|
+
rights?: string[];
|
|
259
|
+
};
|
|
260
|
+
/** ── Provider-user binding (prampta.identity.v2) ──
|
|
261
|
+
* WHO you are acting for. Optional, so existing integrations are
|
|
262
|
+
* unaffected — but once supplied it is held to: it must resolve to an
|
|
263
|
+
* identity link PRAMPTA verified, and a licence belonging to a different
|
|
264
|
+
* end user is refused. Supply either identifier (or both — they must then
|
|
265
|
+
* describe the same person). */
|
|
266
|
+
providerUserId?: string;
|
|
267
|
+
providerIdentityLinkId?: string;
|
|
268
|
+
/** Your own id for this generation attempt. Echoed into the decision so a
|
|
269
|
+
* later receipt can be tied to it without a provider-side lookup table. */
|
|
270
|
+
generationId?: string;
|
|
271
|
+
/** Lets you safely retry a preflight you are unsure landed. */
|
|
272
|
+
idempotencyKey?: string;
|
|
273
|
+
/** Links this call to a prior reportDetection()/confirmDetection() advisory
|
|
274
|
+
* record, purely for audit — never used to decide the outcome. */
|
|
275
|
+
detectionId?: string;
|
|
276
|
+
/** Where to send the end user back to after they buy/request a licence via
|
|
277
|
+
* the returned decision's `remediation.url` (set only on PG_NO_LICENSE) —
|
|
278
|
+
* same idea as Connect AI's connect_return_url. Omit to leave them on
|
|
279
|
+
* prampta.com after they act. */
|
|
280
|
+
returnUrl?: string;
|
|
281
|
+
/** Protocol version negotiation: declares the decision schema THIS CALL
|
|
282
|
+
* expects (e.g. "pg.decision.v1"). A mismatch refuses with 409 before any
|
|
283
|
+
* licensing work happens, instead of silently misreading a future schema.
|
|
284
|
+
* Optional — omit to keep today's behavior. Discover the server's current
|
|
285
|
+
* version via GET /version -> protocol_versions.decision_schema. See
|
|
286
|
+
* docs/PRAMPTA-Protocol-Versions.md. */
|
|
287
|
+
expectedSchemaVersion?: string;
|
|
288
|
+
}
|
|
289
|
+
/** Options for the flat `pg.verify(subjectId, options)` convenience call. */
|
|
290
|
+
interface VerifyOptions extends Omit<VerifyRequest, "subjectId"> {
|
|
291
|
+
categories?: string[];
|
|
292
|
+
channel?: string;
|
|
293
|
+
productName?: string;
|
|
294
|
+
projectName?: string;
|
|
295
|
+
territory?: string;
|
|
296
|
+
campaignId?: string;
|
|
297
|
+
useCase?: string;
|
|
298
|
+
rights?: string[];
|
|
299
|
+
}
|
|
300
|
+
interface SignedDecision {
|
|
301
|
+
schemaVersion: string;
|
|
302
|
+
decisionId: string;
|
|
303
|
+
allowed: boolean;
|
|
304
|
+
reason: string | null;
|
|
305
|
+
subjectId: string;
|
|
306
|
+
licenseeId: string;
|
|
307
|
+
providerId: string;
|
|
308
|
+
licenseId: string | null;
|
|
309
|
+
promptHash: string;
|
|
310
|
+
model: string;
|
|
311
|
+
modality: string;
|
|
312
|
+
intendedUse: Record<string, unknown>;
|
|
313
|
+
obligations: Record<string, unknown>;
|
|
314
|
+
rulesText: string;
|
|
315
|
+
rulesTextHash: string;
|
|
316
|
+
watermarkPayload: string | null;
|
|
317
|
+
isHardRefusal: boolean;
|
|
318
|
+
issuedAt: number;
|
|
319
|
+
expiresAt: number;
|
|
320
|
+
operatorKeyId: string;
|
|
321
|
+
operatorSignature: string;
|
|
322
|
+
/** Strongest authority backing the subject: self | agency_asserted |
|
|
323
|
+
* consented | verified. "self" is only the registrant's own claim. */
|
|
324
|
+
subjectAuthority: string;
|
|
325
|
+
denied: boolean;
|
|
326
|
+
/** Outcome (§8): "allow" | "deny" | "review" | "not_blocked". `allowed` stays
|
|
327
|
+
* the boolean; a REVIEW is allowed=false + disposition="review" — hold for a
|
|
328
|
+
* human, not a flat refusal. "not_blocked" (NMP Q13) is personal use with no
|
|
329
|
+
* licence: PRAMPTA does not object but grants nothing (reason
|
|
330
|
+
* PG_STD_TRACKING_ONLY). Older code reading only `allowed` fails closed. */
|
|
331
|
+
disposition: string;
|
|
332
|
+
/** Policy version that produced this decision. */
|
|
333
|
+
policyVersion: string;
|
|
334
|
+
/** §7 freshness controls. `revocationEpoch` is the subject's epoch at
|
|
335
|
+
* issuance — compare it against GET /subjects/{id}/epoch to learn cheaply
|
|
336
|
+
* whether anything happened since (revoke, dispute, lifecycle change)
|
|
337
|
+
* without re-running verify(). `maxCacheAgeSeconds` and `cacheScope` say
|
|
338
|
+
* whether and how long this exact decision may be reused without a live
|
|
339
|
+
* re-check; only a plain ALLOW is ever cacheable. */
|
|
340
|
+
revocationEpoch: number;
|
|
341
|
+
maxCacheAgeSeconds: number;
|
|
342
|
+
cacheScope: string;
|
|
343
|
+
/** Provider-user binding: "verified" — bound to an end-user identity
|
|
344
|
+
* PRAMPTA verified; "unbound" — no end user was asserted; "invalid" — an
|
|
345
|
+
* assertion was made and failed (always accompanies a deny). */
|
|
346
|
+
providerUserBinding: string;
|
|
347
|
+
/** Which identity link was used, when one was. */
|
|
348
|
+
providerIdentityLinkId: string;
|
|
349
|
+
/** Echoed back from the request, for receipt matching. */
|
|
350
|
+
generationId: string;
|
|
351
|
+
/** Echoed back from the request — links to a detection advisory record. */
|
|
352
|
+
detectionId: string;
|
|
353
|
+
/** Set only when reason === "PG_NO_LICENSE": a direct link to buy/request a
|
|
354
|
+
* licence for this exact subject, plus the one canonical explanation text
|
|
355
|
+
* (show it before redirecting — every integration should read the same
|
|
356
|
+
* wording). null on every other outcome, including allow and refusals a
|
|
357
|
+
* licence purchase would not fix. */
|
|
358
|
+
remediation: {
|
|
359
|
+
url: string;
|
|
360
|
+
message: string;
|
|
361
|
+
} | null;
|
|
362
|
+
}
|
|
363
|
+
interface SubjectInfo {
|
|
364
|
+
subjectId: string;
|
|
365
|
+
status: string;
|
|
366
|
+
visibility: string;
|
|
367
|
+
rulesText: string;
|
|
368
|
+
aliases: string[];
|
|
369
|
+
publicKeyHex?: string;
|
|
370
|
+
publicKeyFingerprint?: string;
|
|
371
|
+
registeredAt: string;
|
|
372
|
+
}
|
|
373
|
+
interface LicenseRequestInput {
|
|
374
|
+
subjectId: string;
|
|
375
|
+
useCase: "commercial" | "editorial" | "personal" | "educational" | "research";
|
|
376
|
+
purpose?: string;
|
|
377
|
+
durationDays?: number;
|
|
378
|
+
message?: string;
|
|
379
|
+
}
|
|
380
|
+
interface LicenseRequestResult {
|
|
381
|
+
requestId: string;
|
|
382
|
+
status: string;
|
|
383
|
+
}
|
|
384
|
+
interface OutputMetadata {
|
|
385
|
+
prampta_decision_id: string;
|
|
386
|
+
prampta_license_id: string | null;
|
|
387
|
+
prampta_watermark: string | null;
|
|
388
|
+
prampta_obligations: Record<string, unknown>;
|
|
389
|
+
prampta_issued_at: number;
|
|
390
|
+
}
|
|
391
|
+
declare class PramptaError extends Error {
|
|
392
|
+
constructor(message: string);
|
|
393
|
+
}
|
|
394
|
+
declare class PramptaNetworkError extends PramptaError {
|
|
395
|
+
readonly cause_: unknown;
|
|
396
|
+
constructor(cause_: unknown);
|
|
397
|
+
}
|
|
398
|
+
declare class PramptaTimeoutError extends PramptaError {
|
|
399
|
+
readonly timeoutMs: number;
|
|
400
|
+
constructor(timeoutMs: number);
|
|
401
|
+
}
|
|
402
|
+
declare class PramptaApiError extends PramptaError {
|
|
403
|
+
readonly status: number;
|
|
404
|
+
readonly detail: string;
|
|
405
|
+
constructor(status: number, detail: string);
|
|
406
|
+
}
|
|
407
|
+
declare class PramptaSchemaError extends PramptaError {
|
|
408
|
+
constructor(message: string);
|
|
409
|
+
}
|
|
410
|
+
/** Operator signature verification failed — decision cannot be trusted. */
|
|
411
|
+
declare class PramptaSignatureError extends PramptaError {
|
|
412
|
+
constructor(message: string);
|
|
413
|
+
}
|
|
414
|
+
declare class PramptaRefusalError extends PramptaError {
|
|
415
|
+
readonly decision: SignedDecision;
|
|
416
|
+
constructor(decision: SignedDecision);
|
|
417
|
+
get reason(): string;
|
|
418
|
+
get isHardRefusal(): boolean;
|
|
419
|
+
get decisionId(): string;
|
|
420
|
+
get licenseId(): string | null;
|
|
421
|
+
}
|
|
422
|
+
declare class PramptaFailClosedError extends PramptaError {
|
|
423
|
+
readonly cause_: unknown;
|
|
424
|
+
constructor(cause_: unknown);
|
|
425
|
+
}
|
|
426
|
+
declare const REFUSAL_DESCRIPTIONS: Record<string, string>;
|
|
427
|
+
declare const HARD_REFUSAL_CODES: Set<string>;
|
|
428
|
+
declare const SOFT_REFUSAL_CODES: Set<string>;
|
|
429
|
+
/** SHA-256 of a prompt — what a decision gets bound to. Standalone twin of
|
|
430
|
+
* `Prampta.hashPrompt` so it can be imported directly. */
|
|
431
|
+
declare function hashPrompt(prompt: string): Promise<string>;
|
|
432
|
+
/**
|
|
433
|
+
* Client-side Merkle inclusion-proof verification (PRE-GEN v1.1 addendum
|
|
434
|
+
* §10, Anchored Audit Profile). Mirror of the registry's own
|
|
435
|
+
* `app/core/merkle.py` — same algorithm, same odd-node handling — so a
|
|
436
|
+
* proof from `Prampta.getInclusionProof()` can be checked entirely
|
|
437
|
+
* offline against a root hash you already trust, without the registry
|
|
438
|
+
* being a party to its own audit.
|
|
439
|
+
*
|
|
440
|
+
* `proof` is the array PRAMPTA returns as `inclusion_proof.proof` — each
|
|
441
|
+
* step `{hash: <sibling hash>, position: "left"|"right"}`. Returns true
|
|
442
|
+
* only if `leafHash` is genuinely one of the leaves committed to by
|
|
443
|
+
* `rootHash`.
|
|
444
|
+
*/
|
|
445
|
+
declare function verifyMerkleProof(leafHash: string, proof: Array<{
|
|
446
|
+
hash: string;
|
|
447
|
+
position: "left" | "right";
|
|
448
|
+
}>, rootHash: string): Promise<boolean>;
|
|
449
|
+
/** One entry of the /v1/subjects/index detection index. */
|
|
450
|
+
interface SubjectIndexEntry {
|
|
451
|
+
subject_id: string;
|
|
452
|
+
aliases: string[];
|
|
453
|
+
status: string;
|
|
454
|
+
visibility: string;
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* Canonical normalization for subject matching: lowercase, strip Latin
|
|
458
|
+
* diacritics, de-leet, -/_ → space, strip punctuation, collapse whitespace.
|
|
459
|
+
* Must stay behaviorally identical to the Python SDK's normalize_for_match.
|
|
460
|
+
*/
|
|
461
|
+
declare function normalizeForMatch(text: string): string;
|
|
462
|
+
/**
|
|
463
|
+
* Detect which index entries are mentioned in `text`. Whole-word phrase
|
|
464
|
+
* containment, plus a squeezed-substring fallback (min length) that defeats
|
|
465
|
+
* letter-spacing ("a d a") and concatenation ("AdaLovelace"). Baseline layer —
|
|
466
|
+
* text only; image/voice detection is provider-side perceptual work.
|
|
467
|
+
*/
|
|
468
|
+
declare function matchSubjects(text: string, entries: SubjectIndexEntry[]): SubjectIndexEntry[];
|
|
469
|
+
declare class Prampta {
|
|
470
|
+
private readonly baseUrl;
|
|
471
|
+
private readonly providerId;
|
|
472
|
+
private readonly licenseeId;
|
|
473
|
+
private readonly token;
|
|
474
|
+
private readonly timeoutMs;
|
|
475
|
+
private readonly maxRetries;
|
|
476
|
+
private readonly retryBackoffMs;
|
|
477
|
+
private readonly failClosed;
|
|
478
|
+
private readonly verifySignature;
|
|
479
|
+
private readonly enforce;
|
|
480
|
+
private readonly requireUserBinding;
|
|
481
|
+
private readonly registryDirectory?;
|
|
482
|
+
private readonly pregenDirectory?;
|
|
483
|
+
private pinnedKeys;
|
|
484
|
+
private keySetCache;
|
|
485
|
+
private keySetPromise;
|
|
486
|
+
private tofuWarned;
|
|
487
|
+
constructor(config?: PramptaConfig);
|
|
488
|
+
/** V-11: a PG code is answered only by the registry that owns its namespace. */
|
|
489
|
+
private assertPregenEndpoint;
|
|
490
|
+
/** Fetch /keys and check it is self-signed by its current key. Cached. */
|
|
491
|
+
private fetchVerifiedKeySet;
|
|
492
|
+
/**
|
|
493
|
+
* Public key hex to verify a decision signed by `keyId`, enforcing the
|
|
494
|
+
* pinning trust model. A pinned match returns immediately (no network); an
|
|
495
|
+
* unpinned key id fails closed in pinned mode; unpinned/TOFU mode resolves
|
|
496
|
+
* from the self-consistent /keys set with a warning.
|
|
497
|
+
*/
|
|
498
|
+
private resolveOperatorKey;
|
|
499
|
+
private subjectIndexEntries;
|
|
500
|
+
private subjectIndexFetchedAt;
|
|
501
|
+
private static readonly SUBJECT_INDEX_TTL_MS;
|
|
502
|
+
/** Fetch the raw subject detection index (/v1/subjects/index). */
|
|
503
|
+
fetchSubjectIndex(): Promise<{
|
|
504
|
+
version: number;
|
|
505
|
+
count: number;
|
|
506
|
+
subjects: SubjectIndexEntry[];
|
|
507
|
+
}>;
|
|
508
|
+
/**
|
|
509
|
+
* Detect registered subjects mentioned in `text`, using a TTL-cached
|
|
510
|
+
* copy of the subject index. Call verify()/assertAllowed() per hit.
|
|
511
|
+
*/
|
|
512
|
+
matchSubjects(text: string, opts?: {
|
|
513
|
+
forceRefresh?: boolean;
|
|
514
|
+
}): Promise<SubjectIndexEntry[]>;
|
|
515
|
+
/** Record what a local text match found for a prompt, BEFORE the user
|
|
516
|
+
* answers. Purely advisory — creates no entitlement or licence. Pass the
|
|
517
|
+
* returned detectionId to confirmDetection() and optionally to verify(). */
|
|
518
|
+
reportDetection(promptHash: string, candidateSubjectIds: string[]): Promise<{
|
|
519
|
+
detectionId: string;
|
|
520
|
+
status: string;
|
|
521
|
+
candidateSubjectIds: string[];
|
|
522
|
+
confirmedSubjectId: string | null;
|
|
523
|
+
createdAt: string;
|
|
524
|
+
confirmedAt: string | null;
|
|
525
|
+
}>;
|
|
526
|
+
/** Record what the user actually said. `subjectId` undefined/null means
|
|
527
|
+
* they rejected every candidate. Still advisory-only. */
|
|
528
|
+
confirmDetection(detectionId: string, subjectId?: string | null): Promise<{
|
|
529
|
+
detectionId: string;
|
|
530
|
+
status: string;
|
|
531
|
+
candidateSubjectIds: string[];
|
|
532
|
+
confirmedSubjectId: string | null;
|
|
533
|
+
createdAt: string;
|
|
534
|
+
confirmedAt: string | null;
|
|
535
|
+
}>;
|
|
536
|
+
/**
|
|
537
|
+
* Verify operator Ed25519 signature over decision body.
|
|
538
|
+
* Fails closed on any error.
|
|
539
|
+
*/
|
|
540
|
+
private verifyDecision;
|
|
541
|
+
/**
|
|
542
|
+
* Verify that the signed decision is bound to the correct request context.
|
|
543
|
+
* Prevents replay attacks where a valid decision for one context is used in another.
|
|
544
|
+
*/
|
|
545
|
+
private verifyContextBinding;
|
|
546
|
+
verifyGeneration(request: VerifyRequest): Promise<SignedDecision>;
|
|
547
|
+
/** Flat convenience API mirroring the Python SDK: intended-use fields
|
|
548
|
+
* (categories, channel, productName, …) are accepted at the top level.
|
|
549
|
+
* Either `prompt` or `promptHash` is REQUIRED — decisions are bound to
|
|
550
|
+
* the prompt hash and the SDK refuses to request unbound ones. */
|
|
551
|
+
verify(subjectId: string, options?: VerifyOptions): Promise<SignedDecision>;
|
|
552
|
+
assertAllowed(subjectId: string, options?: Omit<VerifyRequest, "subjectId">): Promise<SignedDecision>;
|
|
553
|
+
/** Strict license-backed path. Unlike assertAllowed, this never accepts
|
|
554
|
+
* reporting-only not_blocked, an internal no-license allow, or monitor mode.
|
|
555
|
+
* It validates an authorization; it does not prove output compliance. */
|
|
556
|
+
assertLicensed(subjectId: string, options?: Omit<VerifyRequest, "subjectId">): Promise<SignedDecision>;
|
|
557
|
+
withAuthorization<T>(request: VerifyRequest, generateFn: (decision: SignedDecision) => Promise<T>): Promise<{
|
|
558
|
+
output: T;
|
|
559
|
+
decision: SignedDecision;
|
|
560
|
+
metadata: OutputMetadata;
|
|
561
|
+
}>;
|
|
562
|
+
getSubject(subjectId: string): Promise<SubjectInfo | null>;
|
|
563
|
+
requestLicense(input: LicenseRequestInput): Promise<LicenseRequestResult>;
|
|
564
|
+
createOutputMetadata(decision: SignedDecision): OutputMetadata;
|
|
565
|
+
/**
|
|
566
|
+
* Report an output after generation. With a registered provider signing key,
|
|
567
|
+
* opt into v3 so eventType is bound to the provider's signature. This is a
|
|
568
|
+
* provider attestation, not proof of complete reporting or actual execution.
|
|
569
|
+
*/
|
|
570
|
+
submitReceipt(decision: SignedDecision, result?: {
|
|
571
|
+
outputHash?: string;
|
|
572
|
+
model?: string;
|
|
573
|
+
watermarkEmbedded?: boolean;
|
|
574
|
+
obligationsApplied?: Record<string, unknown>;
|
|
575
|
+
generatedAt?: number;
|
|
576
|
+
eventType?: "preview" | "output_accepted" | "output_delivered" | "output_published";
|
|
577
|
+
/** 32-byte Ed25519 private key, hex; keep server-side. Never sent to PRAMPTA. */
|
|
578
|
+
providerSigningKeyHex?: string;
|
|
579
|
+
}): Promise<Record<string, unknown>>;
|
|
580
|
+
/**
|
|
581
|
+
* Get (issuing if needed) the signed `pg.assertion.v1` for a decision this
|
|
582
|
+
* provider/licensee pair already submitted a receipt for — embed it in
|
|
583
|
+
* your OWN C2PA manifest (PRAMPTA does not build the manifest itself).
|
|
584
|
+
* Idempotent: safe to call again for the same decisionId, always returns
|
|
585
|
+
* the same assertion. Requires `submitReceipt()` to have run first.
|
|
586
|
+
*/
|
|
587
|
+
createAssertion(decisionId: string): Promise<Record<string, unknown>>;
|
|
588
|
+
/** Fetch a previously issued assertion. Public — no auth required, since a
|
|
589
|
+
* third party checking a C2PA manifest's embedded assertion needs to
|
|
590
|
+
* verify it without going through PRAMPTA's own auth. */
|
|
591
|
+
getAssertion(decisionId: string): Promise<Record<string, unknown>>;
|
|
592
|
+
/** The most recently published Merkle root over the audit log. Public,
|
|
593
|
+
* unauthenticated. */
|
|
594
|
+
getMerkleRoot(): Promise<Record<string, unknown>>;
|
|
595
|
+
/** Proof that `eventId` is one of the leaves committed to by a Merkle
|
|
596
|
+
* root, without downloading the rest of the log. Check it offline with
|
|
597
|
+
* the standalone `verifyMerkleProof(eventHash, proof, rootHash)` — don't
|
|
598
|
+
* just trust the 200 response; the proof exists so you don't have to.
|
|
599
|
+
* Public, unauthenticated. */
|
|
600
|
+
getInclusionProof(eventId: string): Promise<Record<string, unknown>>;
|
|
601
|
+
health(): Promise<boolean>;
|
|
602
|
+
version(): Promise<Record<string, unknown>>;
|
|
603
|
+
static hashPrompt(prompt: string): Promise<string>;
|
|
604
|
+
private parseDecision;
|
|
605
|
+
private headers;
|
|
606
|
+
/** Transient errors worth retrying: connectivity, timeout, 429, and 5xx. */
|
|
607
|
+
private isRetryable;
|
|
608
|
+
private withRetry;
|
|
609
|
+
private post;
|
|
610
|
+
private postOnce;
|
|
611
|
+
private get;
|
|
612
|
+
private getOnce;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
export { type DeliveryResult, HARD_REFUSAL_CODES, type LicenseRequestInput, type LicenseRequestResult, type LicenseSignatureInput, type Observation, type ObservationOutbox, type OutputMetadata, Prampta, PramptaApiError, type PramptaConfig, PramptaError, PramptaFailClosedError, PramptaNetworkError, PramptaRefusalError, PramptaReporter, PramptaSchemaError, PramptaSignatureError, PramptaTimeoutError, REFUSAL_DESCRIPTIONS, RegistryDirectoryError, type RegistryDirectoryOptions, type ReportInput, SOFT_REFUSAL_CODES, type SignedDecision, type SubjectIndexEntry, type SubjectInfo, TrustedRegistryDirectory, type VerifyOptions, type VerifyRequest, canonicalJson, hashPrompt, matchSubjects, normalizeForMatch, verifyLicenseSignatures, verifyMerkleProof };
|