@prampta/sdk 0.11.0 → 0.11.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/README.md +5 -3
- package/dist/index.js +9 -6
- package/dist/index.mjs +9 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -40,8 +40,9 @@ exists solely so an already-connected provider keeps working mid-migration.
|
|
|
40
40
|
|
|
41
41
|
`createPregen` speaks the simplified PRE-GEN v5 formats at `/v2`: signed
|
|
42
42
|
answers bound to your request, signed reports, signed acknowledgements. Set it
|
|
43
|
-
up once; wrap each generation in one call. Use 0.11.
|
|
44
|
-
defects found by
|
|
43
|
+
up once; wrap each generation in one call. Use 0.11.1 or later: 0.10.0 and
|
|
44
|
+
0.11.0 had defects found by external reviews (see CHANGELOG). A complete
|
|
45
|
+
program you can run as it stands: https://prampta.com/get-started-v2.md.
|
|
45
46
|
|
|
46
47
|
```typescript
|
|
47
48
|
import pg from "pg";
|
|
@@ -52,7 +53,8 @@ const pregen = createPregen({
|
|
|
52
53
|
providerId: "my-ai",
|
|
53
54
|
token: process.env.PRAMPTA_TOKEN!, // your exchange_secret, server-side only
|
|
54
55
|
providerSigningKeyHex: process.env.PREGEN_SIGNING_KEY!, // your Ed25519 private key (32 bytes hex): signs your reports
|
|
55
|
-
pregenDirectory: await loadPregenDirectory({ previous:
|
|
56
|
+
pregenDirectory: await loadPregenDirectory({ previous: lastAccepted }), // PRAMPTA's keys, namespaces, revocations;
|
|
57
|
+
// lastAccepted: the directory you saved last time (toJSON()), or undefined
|
|
56
58
|
store: postgresStore(new pg.Pool()), // shared by all your workers; table pregen_jobs
|
|
57
59
|
});
|
|
58
60
|
|
package/dist/index.js
CHANGED
|
@@ -494,11 +494,15 @@ async function verifyEnvelope(env, type, role, keyFor) {
|
|
|
494
494
|
if (!ok) throw new PregenError("PG_SIGNATURE", `${type} signature does not verify`);
|
|
495
495
|
return e.body;
|
|
496
496
|
}
|
|
497
|
+
var GRANT_FORMATS = {
|
|
498
|
+
// The id is the SHA-256 of the bytes the licence's registry countersigned.
|
|
499
|
+
"pg.license.v2": (g) => keysWithin(g, ["format", "id", "license_id"]) && typeof g.id === "string" && HEX64.test(g.id) && (g.license_id === void 0 || str(g.license_id))
|
|
500
|
+
};
|
|
497
501
|
function checkBasis(b) {
|
|
498
502
|
if (!isObj(b)) return false;
|
|
499
503
|
if (b.kind === "grant") {
|
|
500
504
|
const g = b.grant;
|
|
501
|
-
return keysWithin(b, ["kind", "grant"]) && isObj(g) &&
|
|
505
|
+
return keysWithin(b, ["kind", "grant"]) && isObj(g) && typeof g.format === "string" && !!GRANT_FORMATS[g.format]?.(g);
|
|
502
506
|
}
|
|
503
507
|
return b.kind === "policy" && keysWithin(b, ["kind", "rule"]) && str(b.rule);
|
|
504
508
|
}
|
|
@@ -579,6 +583,7 @@ function createPregen(config) {
|
|
|
579
583
|
};
|
|
580
584
|
const listed = dir?.registries.find((r) => sameBase(r.api));
|
|
581
585
|
if (dir && !listed) fail2(`${base} is not a registry listed in the PRE-GEN directory`);
|
|
586
|
+
const registryCode = listed ? listed.prefix ? `PG-${listed.prefix}-0` : "PG-0" : "";
|
|
582
587
|
const ready = (async () => {
|
|
583
588
|
const registry = /* @__PURE__ */ new Map();
|
|
584
589
|
for (const p of pins) registry.set(await keyIdOf(unhex(p)), unhex(p));
|
|
@@ -589,10 +594,9 @@ function createPregen(config) {
|
|
|
589
594
|
async function keyFor(keyId) {
|
|
590
595
|
const { registry } = await ready;
|
|
591
596
|
if (pins.length) return registry.get(keyId);
|
|
592
|
-
const code = listed.prefix ? `PG-${listed.prefix}-0` : "PG-0";
|
|
593
597
|
let p = fromDirectory.get(keyId);
|
|
594
598
|
if (!p) {
|
|
595
|
-
p = dir.publicKey(
|
|
599
|
+
p = dir.publicKey(registryCode, keyId).then(unhex, () => {
|
|
596
600
|
fromDirectory.delete(keyId);
|
|
597
601
|
return void 0;
|
|
598
602
|
});
|
|
@@ -600,7 +604,7 @@ function createPregen(config) {
|
|
|
600
604
|
}
|
|
601
605
|
return p;
|
|
602
606
|
}
|
|
603
|
-
const directoryVerdict = (subject, keyId) => !dir
|
|
607
|
+
const directoryVerdict = (subject, keyId) => !dir ? "valid" : dir.checkSigner(isPgCode(subject) ? subject : registryCode, keyId);
|
|
604
608
|
async function post(path, payload) {
|
|
605
609
|
const resp = await fetch(base + path, {
|
|
606
610
|
method: "POST",
|
|
@@ -676,12 +680,11 @@ function createPregen(config) {
|
|
|
676
680
|
return { subject: a.request.subject_ref, answerStatus: a.answer?.body.status ?? "none", report: await seal("pg.report.v1", body) };
|
|
677
681
|
}
|
|
678
682
|
async function checkAck(r, env) {
|
|
679
|
-
const { keyId } = await ready;
|
|
680
683
|
const ack = await verifyEnvelope(env, "pg.report_ack.v1", "registry", keyFor);
|
|
681
684
|
const verdict = directoryVerdict(r.subject, ack.signers[0].key_id);
|
|
682
685
|
if (verdict !== "valid") throw new PregenError(`PG_KEY_${verdict.toUpperCase()}`, "the directory does not list this key");
|
|
683
686
|
if (Object.keys(ack).sort().join() !== [...ACK_FIELDS].sort().join()) throw malformed("acknowledgement fields");
|
|
684
|
-
if (ack.report !== await messageId("pg.report.v1", r.report.body) || ack.answer !== r.report.body.answer || ack.answer_status !== r.answerStatus || ack.provider_key_id !==
|
|
687
|
+
if (ack.report !== await messageId("pg.report.v1", r.report.body) || ack.answer !== r.report.body.answer || ack.answer_status !== r.answerStatus || ack.provider_key_id !== r.report.body.signers?.[0]?.key_id) {
|
|
685
688
|
throw new PregenError("PG_BINDING", "the acknowledgement is not for this report");
|
|
686
689
|
}
|
|
687
690
|
if (!(ack.counted === null || HEX64.test(ack.counted)) || !Array.isArray(ack.released) || !ack.released.every((x) => typeof x === "string" && HEX64.test(x)) || !Number.isSafeInteger(ack.received_at)) {
|
package/dist/index.mjs
CHANGED
|
@@ -429,11 +429,15 @@ async function verifyEnvelope(env, type, role, keyFor) {
|
|
|
429
429
|
if (!ok) throw new PregenError("PG_SIGNATURE", `${type} signature does not verify`);
|
|
430
430
|
return e.body;
|
|
431
431
|
}
|
|
432
|
+
var GRANT_FORMATS = {
|
|
433
|
+
// The id is the SHA-256 of the bytes the licence's registry countersigned.
|
|
434
|
+
"pg.license.v2": (g) => keysWithin(g, ["format", "id", "license_id"]) && typeof g.id === "string" && HEX64.test(g.id) && (g.license_id === void 0 || str(g.license_id))
|
|
435
|
+
};
|
|
432
436
|
function checkBasis(b) {
|
|
433
437
|
if (!isObj(b)) return false;
|
|
434
438
|
if (b.kind === "grant") {
|
|
435
439
|
const g = b.grant;
|
|
436
|
-
return keysWithin(b, ["kind", "grant"]) && isObj(g) &&
|
|
440
|
+
return keysWithin(b, ["kind", "grant"]) && isObj(g) && typeof g.format === "string" && !!GRANT_FORMATS[g.format]?.(g);
|
|
437
441
|
}
|
|
438
442
|
return b.kind === "policy" && keysWithin(b, ["kind", "rule"]) && str(b.rule);
|
|
439
443
|
}
|
|
@@ -514,6 +518,7 @@ function createPregen(config) {
|
|
|
514
518
|
};
|
|
515
519
|
const listed = dir?.registries.find((r) => sameBase(r.api));
|
|
516
520
|
if (dir && !listed) fail2(`${base} is not a registry listed in the PRE-GEN directory`);
|
|
521
|
+
const registryCode = listed ? listed.prefix ? `PG-${listed.prefix}-0` : "PG-0" : "";
|
|
517
522
|
const ready = (async () => {
|
|
518
523
|
const registry = /* @__PURE__ */ new Map();
|
|
519
524
|
for (const p of pins) registry.set(await keyIdOf(unhex(p)), unhex(p));
|
|
@@ -524,10 +529,9 @@ function createPregen(config) {
|
|
|
524
529
|
async function keyFor(keyId) {
|
|
525
530
|
const { registry } = await ready;
|
|
526
531
|
if (pins.length) return registry.get(keyId);
|
|
527
|
-
const code = listed.prefix ? `PG-${listed.prefix}-0` : "PG-0";
|
|
528
532
|
let p = fromDirectory.get(keyId);
|
|
529
533
|
if (!p) {
|
|
530
|
-
p = dir.publicKey(
|
|
534
|
+
p = dir.publicKey(registryCode, keyId).then(unhex, () => {
|
|
531
535
|
fromDirectory.delete(keyId);
|
|
532
536
|
return void 0;
|
|
533
537
|
});
|
|
@@ -535,7 +539,7 @@ function createPregen(config) {
|
|
|
535
539
|
}
|
|
536
540
|
return p;
|
|
537
541
|
}
|
|
538
|
-
const directoryVerdict = (subject, keyId) => !dir
|
|
542
|
+
const directoryVerdict = (subject, keyId) => !dir ? "valid" : dir.checkSigner(isPgCode(subject) ? subject : registryCode, keyId);
|
|
539
543
|
async function post(path, payload) {
|
|
540
544
|
const resp = await fetch(base + path, {
|
|
541
545
|
method: "POST",
|
|
@@ -611,12 +615,11 @@ function createPregen(config) {
|
|
|
611
615
|
return { subject: a.request.subject_ref, answerStatus: a.answer?.body.status ?? "none", report: await seal("pg.report.v1", body) };
|
|
612
616
|
}
|
|
613
617
|
async function checkAck(r, env) {
|
|
614
|
-
const { keyId } = await ready;
|
|
615
618
|
const ack = await verifyEnvelope(env, "pg.report_ack.v1", "registry", keyFor);
|
|
616
619
|
const verdict = directoryVerdict(r.subject, ack.signers[0].key_id);
|
|
617
620
|
if (verdict !== "valid") throw new PregenError(`PG_KEY_${verdict.toUpperCase()}`, "the directory does not list this key");
|
|
618
621
|
if (Object.keys(ack).sort().join() !== [...ACK_FIELDS].sort().join()) throw malformed("acknowledgement fields");
|
|
619
|
-
if (ack.report !== await messageId("pg.report.v1", r.report.body) || ack.answer !== r.report.body.answer || ack.answer_status !== r.answerStatus || ack.provider_key_id !==
|
|
622
|
+
if (ack.report !== await messageId("pg.report.v1", r.report.body) || ack.answer !== r.report.body.answer || ack.answer_status !== r.answerStatus || ack.provider_key_id !== r.report.body.signers?.[0]?.key_id) {
|
|
620
623
|
throw new PregenError("PG_BINDING", "the acknowledgement is not for this report");
|
|
621
624
|
}
|
|
622
625
|
if (!(ack.counted === null || HEX64.test(ack.counted)) || !Array.isArray(ack.released) || !ack.released.every((x) => typeof x === "string" && HEX64.test(x)) || !Number.isSafeInteger(ack.received_at)) {
|