@prampta/sdk 0.4.0 → 0.8.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/dist/index.d.mts CHANGED
@@ -1,3 +1,125 @@
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
+
1
123
  /**
2
124
  * PRAMPTA SDK for TypeScript / Node.js
3
125
  *
@@ -11,26 +133,47 @@
11
133
  * const pg = new Prampta({
12
134
  * baseUrl: "https://api2.prampta.com",
13
135
  * providerId: "my-ai-service",
14
- * licenseeId: "acme-corp",
15
- * token: "pair-token",
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,
16
141
  * });
17
142
  *
18
143
  * // Throws if denied — fail-closed by default
19
- * await pg.assertAllowed("leonardo-da-vinci", {
20
- * prompt: "Da Vinci in a documentary",
144
+ * await pg.assertAllowed("sbx-allowed", {
145
+ * prompt: "A sandbox portrait",
21
146
  * modality: "image",
22
- * model: "gpt-image-1",
147
+ * model: "your-model",
148
+ * intendedUse: { useCase: "research" },
23
149
  * });
24
150
  * ```
25
151
  */
152
+
26
153
  interface PramptaConfig {
27
154
  /** The PRAMPTA registry URL. Falls back to PRAMPTA_BASE_URL env var. */
28
155
  baseUrl?: string;
29
156
  /** Your provider ID. Falls back to PRAMPTA_PROVIDER_ID env var. */
30
157
  providerId?: string;
31
- /** The licensee ID. Falls back to PRAMPTA_LICENSEE_ID env var. */
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"`. */
32
161
  licenseeId?: string;
33
- /** The pair authentication token. Falls back to PRAMPTA_TOKEN env var. */
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
+ */
34
177
  token?: string;
35
178
  /** Request timeout in milliseconds (default 3000). */
36
179
  timeoutMs?: number;
@@ -65,6 +208,27 @@ interface PramptaConfig {
65
208
  * Set to false ONLY for local development — never in production.
66
209
  */
67
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;
68
232
  }
69
233
  interface VerifyRequest {
70
234
  /** Subject to verify authorization for. */
@@ -84,7 +248,43 @@ interface VerifyRequest {
84
248
  projectName?: string;
85
249
  categories?: string[];
86
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[];
87
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;
88
288
  }
89
289
  /** Options for the flat `pg.verify(subjectId, options)` convenience call. */
90
290
  interface VerifyOptions extends Omit<VerifyRequest, "subjectId"> {
@@ -93,6 +293,9 @@ interface VerifyOptions extends Omit<VerifyRequest, "subjectId"> {
93
293
  productName?: string;
94
294
  projectName?: string;
95
295
  territory?: string;
296
+ campaignId?: string;
297
+ useCase?: string;
298
+ rights?: string[];
96
299
  }
97
300
  interface SignedDecision {
98
301
  schemaVersion: string;
@@ -120,6 +323,42 @@ interface SignedDecision {
120
323
  * consented | verified. "self" is only the registrant's own claim. */
121
324
  subjectAuthority: string;
122
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;
123
362
  }
124
363
  interface SubjectInfo {
125
364
  subjectId: string;
@@ -142,6 +381,36 @@ interface LicenseRequestResult {
142
381
  requestId: string;
143
382
  status: string;
144
383
  }
384
+ /** One generation as `generateAuthorized` records it. Stored by the
385
+ * provider, in its own database, so a crash never leads to generating twice. */
386
+ interface GenerationJournalEntry {
387
+ generationId: string;
388
+ /** authorized: allows held, generation may have started.
389
+ * generated: output exists, receipts may be missing.
390
+ * reported: receipts filed. released: nothing produced, allows given back. */
391
+ stage: "authorized" | "generated" | "reported" | "released";
392
+ decisions: SignedDecision[];
393
+ outputHash?: string;
394
+ }
395
+ interface GenerationJournal {
396
+ get(generationId: string): Promise<GenerationJournalEntry | null>;
397
+ /** Resolve only after a durable write. */
398
+ put(entry: GenerationJournalEntry): Promise<void>;
399
+ }
400
+ type ReceiptOptions = Omit<NonNullable<Parameters<Prampta["submitReceipt"]>[1]>, "outputHash">;
401
+ interface AuthorizedGeneration<T> {
402
+ /** generated: ran now. recovered: output existed from an earlier run, only
403
+ * receipts were sent. already_reported: nothing left to do. */
404
+ status: "generated" | "recovered" | "already_reported";
405
+ /** Only for status "generated"; after a recovery the output is wherever
406
+ * your earlier run stored it. */
407
+ output?: T;
408
+ decisions: SignedDecision[];
409
+ outputHash: string;
410
+ /** Receipts that could not be filed yet. Call again with the same
411
+ * generationId (needs a journal) or submitReceipt() for each. */
412
+ unreported: SignedDecision[];
413
+ }
145
414
  interface OutputMetadata {
146
415
  prampta_decision_id: string;
147
416
  prampta_license_id: string | null;
@@ -191,16 +460,22 @@ declare const SOFT_REFUSAL_CODES: Set<string>;
191
460
  * `Prampta.hashPrompt` so it can be imported directly. */
192
461
  declare function hashPrompt(prompt: string): Promise<string>;
193
462
  /**
194
- * Canonical JSON — deterministic serialization matching Python's
195
- * `json.dumps(obj, sort_keys=True, separators=(",",":"), ensure_ascii=False)`.
196
- * Required for signature verification across languages.
463
+ * Client-side Merkle inclusion-proof verification (PRE-GEN v1.1 addendum
464
+ * §10, Anchored Audit Profile). Mirror of the registry's own
465
+ * `app/core/merkle.py` — same algorithm, same odd-node handling — so a
466
+ * proof from `Prampta.getInclusionProof()` can be checked entirely
467
+ * offline against a root hash you already trust, without the registry
468
+ * being a party to its own audit.
197
469
  *
198
- * Exported so external verifiers can rebuild signed bodies and so the
199
- * cross-implementation spec test vectors (spec/test-vectors) can pin it.
200
- * Field names in signed protocol bodies are ASCII by construction — key
201
- * sorting is identical to Python's code-point sort in that range.
470
+ * `proof` is the array PRAMPTA returns as `inclusion_proof.proof` — each
471
+ * step `{hash: <sibling hash>, position: "left"|"right"}`. Returns true
472
+ * only if `leafHash` is genuinely one of the leaves committed to by
473
+ * `rootHash`.
202
474
  */
203
- declare function canonicalJson(obj: unknown): string;
475
+ declare function verifyMerkleProof(leafHash: string, proof: Array<{
476
+ hash: string;
477
+ position: "left" | "right";
478
+ }>, rootHash: string): Promise<boolean>;
204
479
  /** One entry of the /v1/subjects/index detection index. */
205
480
  interface SubjectIndexEntry {
206
481
  subject_id: string;
@@ -232,11 +507,17 @@ declare class Prampta {
232
507
  private readonly failClosed;
233
508
  private readonly verifySignature;
234
509
  private readonly enforce;
510
+ private readonly requireUserBinding;
511
+ private readonly registryDirectory?;
512
+ private readonly pregenDirectory?;
235
513
  private pinnedKeys;
236
514
  private keySetCache;
237
515
  private keySetPromise;
238
516
  private tofuWarned;
517
+ private readonly inFlight;
239
518
  constructor(config?: PramptaConfig);
519
+ /** V-11: a PG code is answered only by the registry that owns its namespace. */
520
+ private assertPregenEndpoint;
240
521
  /** Fetch /keys and check it is self-signed by its current key. Cached. */
241
522
  private fetchVerifiedKeySet;
242
523
  /**
@@ -262,6 +543,27 @@ declare class Prampta {
262
543
  matchSubjects(text: string, opts?: {
263
544
  forceRefresh?: boolean;
264
545
  }): Promise<SubjectIndexEntry[]>;
546
+ /** Record what a local text match found for a prompt, BEFORE the user
547
+ * answers. Purely advisory — creates no entitlement or licence. Pass the
548
+ * returned detectionId to confirmDetection() and optionally to verify(). */
549
+ reportDetection(promptHash: string, candidateSubjectIds: string[]): Promise<{
550
+ detectionId: string;
551
+ status: string;
552
+ candidateSubjectIds: string[];
553
+ confirmedSubjectId: string | null;
554
+ createdAt: string;
555
+ confirmedAt: string | null;
556
+ }>;
557
+ /** Record what the user actually said. `subjectId` undefined/null means
558
+ * they rejected every candidate. Still advisory-only. */
559
+ confirmDetection(detectionId: string, subjectId?: string | null): Promise<{
560
+ detectionId: string;
561
+ status: string;
562
+ candidateSubjectIds: string[];
563
+ confirmedSubjectId: string | null;
564
+ createdAt: string;
565
+ confirmedAt: string | null;
566
+ }>;
265
567
  /**
266
568
  * Verify operator Ed25519 signature over decision body.
267
569
  * Fails closed on any error.
@@ -279,18 +581,57 @@ declare class Prampta {
279
581
  * the prompt hash and the SDK refuses to request unbound ones. */
280
582
  verify(subjectId: string, options?: VerifyOptions): Promise<SignedDecision>;
281
583
  assertAllowed(subjectId: string, options?: Omit<VerifyRequest, "subjectId">): Promise<SignedDecision>;
584
+ /** Strict license-backed path. Unlike assertAllowed, this never accepts
585
+ * reporting-only not_blocked, an internal no-license allow, or monitor mode.
586
+ * It validates an authorization; it does not prove output compliance. */
587
+ assertLicensed(subjectId: string, options?: Omit<VerifyRequest, "subjectId">): Promise<SignedDecision>;
282
588
  withAuthorization<T>(request: VerifyRequest, generateFn: (decision: SignedDecision) => Promise<T>): Promise<{
283
589
  output: T;
284
590
  decision: SignedDecision;
285
591
  metadata: OutputMetadata;
286
592
  }>;
593
+ /**
594
+ * The whole cycle in one call, for every subject in the output:
595
+ * ask PRAMPTA fresh for each subject (no cached allow is reused), require a
596
+ * licence-backed allow from all of them, generate, file one receipt per
597
+ * subject. If any subject refuses, or `generate` throws, the allows already
598
+ * held are released so they do not count against usage limits.
599
+ *
600
+ * `generate` must throw only when nothing was produced. With a `journal`,
601
+ * calling again with the same generationId after a crash never generates
602
+ * twice: it resends missing receipts, or refuses if the crash happened
603
+ * mid-generation (then check your own records, releaseDecision() if nothing
604
+ * was produced, and use a new generationId). Concurrent calls with the
605
+ * same generationId in this process share one run.
606
+ */
607
+ generateAuthorized<T>(request: Omit<VerifyRequest, "subjectId" | "generationId"> & {
608
+ subjectIds: string[];
609
+ generationId: string;
610
+ }, generate: (decisions: SignedDecision[]) => Promise<{
611
+ output: T;
612
+ outputHash?: string;
613
+ outputBytes?: Uint8Array | string;
614
+ }>, options?: {
615
+ journal?: GenerationJournal;
616
+ receipt?: ReceiptOptions;
617
+ }): Promise<AuthorizedGeneration<T>>;
618
+ private runAuthorized;
619
+ /** Returns the decisions whose receipt could not be filed. A receipt that
620
+ * already exists (an earlier attempt landed) counts as filed. */
621
+ private fileReceipts;
622
+ /** True when every allow was given back. */
623
+ private releaseAll;
624
+ /** Give back an allow that produced nothing (failed or cancelled job), so
625
+ * it does not count against the licence's usage limit. Only before a
626
+ * receipt and within 24 hours; the release is recorded in the audit log. */
627
+ releaseDecision(decisionId: string, reason?: string): Promise<Record<string, unknown>>;
287
628
  getSubject(subjectId: string): Promise<SubjectInfo | null>;
288
629
  requestLicense(input: LicenseRequestInput): Promise<LicenseRequestResult>;
289
630
  createOutputMetadata(decision: SignedDecision): OutputMetadata;
290
631
  /**
291
- * Submit a generation receipt AFTER generating — the provider's enforcement
292
- * proof, bound to the decision it acted on. Records that this generation was
293
- * authorized and executed under the decision's terms (verifiable post-hoc).
632
+ * Report an output after generation. With a registered provider signing key,
633
+ * opt into v3 so eventType is bound to the provider's signature. This is a
634
+ * provider attestation, not proof of complete reporting or actual execution.
294
635
  */
295
636
  submitReceipt(decision: SignedDecision, result?: {
296
637
  outputHash?: string;
@@ -298,7 +639,31 @@ declare class Prampta {
298
639
  watermarkEmbedded?: boolean;
299
640
  obligationsApplied?: Record<string, unknown>;
300
641
  generatedAt?: number;
642
+ eventType?: "preview" | "output_accepted" | "output_delivered" | "output_published";
643
+ /** 32-byte Ed25519 private key, hex; keep server-side. Never sent to PRAMPTA. */
644
+ providerSigningKeyHex?: string;
301
645
  }): Promise<Record<string, unknown>>;
646
+ /**
647
+ * Get (issuing if needed) the signed `pg.assertion.v1` for a decision this
648
+ * provider/licensee pair already submitted a receipt for — embed it in
649
+ * your OWN C2PA manifest (PRAMPTA does not build the manifest itself).
650
+ * Idempotent: safe to call again for the same decisionId, always returns
651
+ * the same assertion. Requires `submitReceipt()` to have run first.
652
+ */
653
+ createAssertion(decisionId: string): Promise<Record<string, unknown>>;
654
+ /** Fetch a previously issued assertion. Public — no auth required, since a
655
+ * third party checking a C2PA manifest's embedded assertion needs to
656
+ * verify it without going through PRAMPTA's own auth. */
657
+ getAssertion(decisionId: string): Promise<Record<string, unknown>>;
658
+ /** The most recently published Merkle root over the audit log. Public,
659
+ * unauthenticated. */
660
+ getMerkleRoot(): Promise<Record<string, unknown>>;
661
+ /** Proof that `eventId` is one of the leaves committed to by a Merkle
662
+ * root, without downloading the rest of the log. Check it offline with
663
+ * the standalone `verifyMerkleProof(eventHash, proof, rootHash)` — don't
664
+ * just trust the 200 response; the proof exists so you don't have to.
665
+ * Public, unauthenticated. */
666
+ getInclusionProof(eventId: string): Promise<Record<string, unknown>>;
302
667
  health(): Promise<boolean>;
303
668
  version(): Promise<Record<string, unknown>>;
304
669
  static hashPrompt(prompt: string): Promise<string>;
@@ -313,4 +678,4 @@ declare class Prampta {
313
678
  private getOnce;
314
679
  }
315
680
 
316
- export { HARD_REFUSAL_CODES, type LicenseRequestInput, type LicenseRequestResult, type OutputMetadata, Prampta, PramptaApiError, type PramptaConfig, PramptaError, PramptaFailClosedError, PramptaNetworkError, PramptaRefusalError, PramptaSchemaError, PramptaSignatureError, PramptaTimeoutError, REFUSAL_DESCRIPTIONS, SOFT_REFUSAL_CODES, type SignedDecision, type SubjectIndexEntry, type SubjectInfo, type VerifyOptions, type VerifyRequest, canonicalJson, hashPrompt, matchSubjects, normalizeForMatch };
681
+ export { type AuthorizedGeneration, type DeliveryResult, type GenerationJournal, type GenerationJournalEntry, 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, type ReceiptOptions, 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 };