@passportsign/core 0.1.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.
Files changed (84) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +36 -0
  3. package/dist/badge.d.ts +37 -0
  4. package/dist/badge.d.ts.map +1 -0
  5. package/dist/badge.js +94 -0
  6. package/dist/badge.js.map +1 -0
  7. package/dist/bind.d.ts +61 -0
  8. package/dist/bind.d.ts.map +1 -0
  9. package/dist/bind.js +79 -0
  10. package/dist/bind.js.map +1 -0
  11. package/dist/bundle.d.ts +47 -0
  12. package/dist/bundle.d.ts.map +1 -0
  13. package/dist/bundle.js +95 -0
  14. package/dist/bundle.js.map +1 -0
  15. package/dist/canonical.d.ts +19 -0
  16. package/dist/canonical.d.ts.map +1 -0
  17. package/dist/canonical.js +30 -0
  18. package/dist/canonical.js.map +1 -0
  19. package/dist/dsse.d.ts +55 -0
  20. package/dist/dsse.d.ts.map +1 -0
  21. package/dist/dsse.js +64 -0
  22. package/dist/dsse.js.map +1 -0
  23. package/dist/errors.d.ts +17 -0
  24. package/dist/errors.d.ts.map +1 -0
  25. package/dist/errors.js +33 -0
  26. package/dist/errors.js.map +1 -0
  27. package/dist/github.d.ts +28 -0
  28. package/dist/github.d.ts.map +1 -0
  29. package/dist/github.js +113 -0
  30. package/dist/github.js.map +1 -0
  31. package/dist/index.d.ts +22 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +27 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/log/rekor.d.ts +91 -0
  36. package/dist/log/rekor.d.ts.map +1 -0
  37. package/dist/log/rekor.js +218 -0
  38. package/dist/log/rekor.js.map +1 -0
  39. package/dist/merkle.d.ts +37 -0
  40. package/dist/merkle.d.ts.map +1 -0
  41. package/dist/merkle.js +160 -0
  42. package/dist/merkle.js.map +1 -0
  43. package/dist/nonce.d.ts +24 -0
  44. package/dist/nonce.d.ts.map +1 -0
  45. package/dist/nonce.js +50 -0
  46. package/dist/nonce.js.map +1 -0
  47. package/dist/sdk-payload.d.ts +33 -0
  48. package/dist/sdk-payload.d.ts.map +1 -0
  49. package/dist/sdk-payload.js +36 -0
  50. package/dist/sdk-payload.js.map +1 -0
  51. package/dist/statement.d.ts +67 -0
  52. package/dist/statement.d.ts.map +1 -0
  53. package/dist/statement.js +67 -0
  54. package/dist/statement.js.map +1 -0
  55. package/dist/storage/sqlite.d.ts +45 -0
  56. package/dist/storage/sqlite.d.ts.map +1 -0
  57. package/dist/storage/sqlite.js +132 -0
  58. package/dist/storage/sqlite.js.map +1 -0
  59. package/dist/submit.d.ts +26 -0
  60. package/dist/submit.d.ts.map +1 -0
  61. package/dist/submit.js +35 -0
  62. package/dist/submit.js.map +1 -0
  63. package/dist/verifier.d.ts +74 -0
  64. package/dist/verifier.d.ts.map +1 -0
  65. package/dist/verifier.js +197 -0
  66. package/dist/verifier.js.map +1 -0
  67. package/package.json +60 -0
  68. package/src/badge.ts +113 -0
  69. package/src/bind.ts +137 -0
  70. package/src/bundle.ts +127 -0
  71. package/src/canonical.ts +33 -0
  72. package/src/dsse.ts +91 -0
  73. package/src/errors.ts +37 -0
  74. package/src/github.ts +196 -0
  75. package/src/index.ts +121 -0
  76. package/src/log/rekor.ts +334 -0
  77. package/src/merkle.ts +187 -0
  78. package/src/nonce.ts +53 -0
  79. package/src/sdk-payload.ts +62 -0
  80. package/src/statement.ts +119 -0
  81. package/src/storage/sqlite.ts +185 -0
  82. package/src/submit.ts +54 -0
  83. package/src/truestamp-canonify.d.ts +7 -0
  84. package/src/verifier.ts +317 -0
package/dist/bundle.js ADDED
@@ -0,0 +1,95 @@
1
+ /**
2
+ * `binding.passportsign.json` bundle format — the portable unit of
3
+ * verification.
4
+ *
5
+ * Rekor stores hashes, not artifacts. To verify a binding, a third party
6
+ * needs both the Rekor entry (hash + inclusion proof) and the artifacts
7
+ * that were hashed. The bundle carries both: the canonical statement bytes
8
+ * (hex), the proof blob (base64), and the Rekor metadata.
9
+ *
10
+ * Shape follows the Sigstore verification-bundle pattern. The
11
+ * `rekor.inclusion_proof` field is intentionally `unknown` for now — its
12
+ * shape gets pinned in Day 5 after we've smoke-tested the public Sigstore
13
+ * Rekor response format.
14
+ */
15
+ import { readFileSync, writeFileSync } from 'node:fs';
16
+ export const BUNDLE_FORMAT_VERSION = 1;
17
+ const HEX_EVEN = /^(?:[0-9a-f]{2})+$/;
18
+ // Standard base64: A-Z, a-z, 0-9, +, /, with 0-2 trailing '=' for padding.
19
+ // Length must be multiple of 4.
20
+ const BASE64 = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;
21
+ export class BundleValidationError extends Error {
22
+ path;
23
+ constructor(path, message) {
24
+ super(`${path}: ${message}`);
25
+ this.path = path;
26
+ this.name = 'BundleValidationError';
27
+ }
28
+ }
29
+ function fail(path, message) {
30
+ throw new BundleValidationError(path, message);
31
+ }
32
+ function isObject(v) {
33
+ return typeof v === 'object' && v !== null && !Array.isArray(v);
34
+ }
35
+ /**
36
+ * Type-guard validator for `PassportsignBundle`. Throws
37
+ * `BundleValidationError` with a structured path on the first issue.
38
+ */
39
+ export function validateBundle(value) {
40
+ if (!isObject(value))
41
+ fail('$', 'bundle must be a JSON object');
42
+ if (value['bundle_format_version'] !== BUNDLE_FORMAT_VERSION) {
43
+ fail('$.bundle_format_version', `expected ${BUNDLE_FORMAT_VERSION}, got ${JSON.stringify(value['bundle_format_version'])}`);
44
+ }
45
+ const statement = value['statement'];
46
+ if (typeof statement !== 'string')
47
+ fail('$.statement', 'must be a string');
48
+ if (!HEX_EVEN.test(statement)) {
49
+ fail('$.statement', 'must be lowercase even-length hex (canonical JCS bytes)');
50
+ }
51
+ const proofBlob = value['proof_blob'];
52
+ if (typeof proofBlob !== 'string')
53
+ fail('$.proof_blob', 'must be a string');
54
+ if (!BASE64.test(proofBlob)) {
55
+ fail('$.proof_blob', 'must be standard base64 (A-Z, a-z, 0-9, +, /, = padding)');
56
+ }
57
+ const rekor = value['rekor'];
58
+ if (!isObject(rekor))
59
+ fail('$.rekor', 'must be an object');
60
+ const logEntryHash = rekor['log_entry_hash'];
61
+ if (typeof logEntryHash !== 'string' || logEntryHash.length === 0) {
62
+ fail('$.rekor.log_entry_hash', 'must be a non-empty string');
63
+ }
64
+ if (!('inclusion_proof' in rekor)) {
65
+ fail('$.rekor.inclusion_proof', 'is required (shape pinned in Day 5)');
66
+ }
67
+ const logRootAtSubmission = rekor['log_root_at_submission'];
68
+ if (typeof logRootAtSubmission !== 'string' || logRootAtSubmission.length === 0) {
69
+ fail('$.rekor.log_root_at_submission', 'must be a non-empty string');
70
+ }
71
+ }
72
+ /**
73
+ * Read and validate a `binding.passportsign.json` file. Throws on
74
+ * invalid JSON or schema violations.
75
+ */
76
+ export function readBundle(path) {
77
+ const raw = readFileSync(path, 'utf8');
78
+ let parsed;
79
+ try {
80
+ parsed = JSON.parse(raw);
81
+ }
82
+ catch (err) {
83
+ throw new BundleValidationError('$', `invalid JSON: ${err instanceof Error ? err.message : String(err)}`);
84
+ }
85
+ validateBundle(parsed);
86
+ return parsed;
87
+ }
88
+ /**
89
+ * Validate and write a `binding.passportsign.json` file (pretty-printed).
90
+ */
91
+ export function writeBundle(path, bundle) {
92
+ validateBundle(bundle);
93
+ writeFileSync(path, JSON.stringify(bundle, null, 2) + '\n', 'utf8');
94
+ }
95
+ //# sourceMappingURL=bundle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bundle.js","sourceRoot":"","sources":["../src/bundle.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * RFC 8785 JCS-canonical UTF-8 bytes for a JSON-serializable value.
3
+ *
4
+ * Wraps `@truestamp/canonify` (pinned at exact 1.0.3) and UTF-8 encodes the
5
+ * resulting string. The fixture-pinned drift test in
6
+ * `test/canonical.test.ts` guards against silent behavior changes in the
7
+ * underlying library — JCS implementations have had subtle bugs and this
8
+ * function's output is the most security-critical artifact in the repo.
9
+ *
10
+ * Throws `TypeError` if the value cannot be canonicalized (e.g. undefined,
11
+ * cycles, non-JSON-serializable types).
12
+ */
13
+ export declare function canonicalize(value: unknown): Uint8Array;
14
+ /**
15
+ * Lowercase-hex SHA-256 of `canonicalize(value)`. Used to derive the
16
+ * Rekor entry hash for the in-toto statement.
17
+ */
18
+ export declare function canonicalSha256Hex(value: unknown): string;
19
+ //# sourceMappingURL=canonical.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canonical.d.ts","sourceRoot":"","sources":["../src/canonical.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,UAAU,CAQvD;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAGzD"}
@@ -0,0 +1,30 @@
1
+ import canonify from '@truestamp/canonify';
2
+ import { createHash } from 'node:crypto';
3
+ /**
4
+ * RFC 8785 JCS-canonical UTF-8 bytes for a JSON-serializable value.
5
+ *
6
+ * Wraps `@truestamp/canonify` (pinned at exact 1.0.3) and UTF-8 encodes the
7
+ * resulting string. The fixture-pinned drift test in
8
+ * `test/canonical.test.ts` guards against silent behavior changes in the
9
+ * underlying library — JCS implementations have had subtle bugs and this
10
+ * function's output is the most security-critical artifact in the repo.
11
+ *
12
+ * Throws `TypeError` if the value cannot be canonicalized (e.g. undefined,
13
+ * cycles, non-JSON-serializable types).
14
+ */
15
+ export function canonicalize(value) {
16
+ const canonical = canonify(value);
17
+ if (canonical === undefined) {
18
+ throw new TypeError('canonicalize: value cannot be JCS-canonicalized (undefined / cycle / non-JSON)');
19
+ }
20
+ return new TextEncoder().encode(canonical);
21
+ }
22
+ /**
23
+ * Lowercase-hex SHA-256 of `canonicalize(value)`. Used to derive the
24
+ * Rekor entry hash for the in-toto statement.
25
+ */
26
+ export function canonicalSha256Hex(value) {
27
+ const bytes = canonicalize(value);
28
+ return createHash('sha256').update(bytes).digest('hex');
29
+ }
30
+ //# sourceMappingURL=canonical.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canonical.js","sourceRoot":"","sources":["../src/canonical.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,qBAAqB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,YAAY,CAAC,KAAc;IACzC,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAClC,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,MAAM,IAAI,SAAS,CACjB,gFAAgF,CACjF,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;AAC7C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAc;IAC/C,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IAClC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC1D,CAAC"}
package/dist/dsse.d.ts ADDED
@@ -0,0 +1,55 @@
1
+ /**
2
+ * DSSE (Dead Simple Signing Envelope) envelope builder.
3
+ *
4
+ * Per-binding ephemeral ECDSA P-256 key — the private key is discarded
5
+ * after signing. The DSSE signature is a Rekor schema requirement, not
6
+ * a trust mechanism. The actual authentication for passportsign comes
7
+ * from the zkPassport proof + GitHub gist evidence carried inside the
8
+ * statement's predicate, not from this signature.
9
+ *
10
+ * Spec: https://github.com/secure-systems-lab/dsse/blob/master/protocol.md
11
+ *
12
+ * Note on key algorithm choice: ECDSA P-256 over SHA-256 is what
13
+ * Rekor's public instance accepts for intoto v0.0.2 entries. Ed25519
14
+ * is in the DSSE spec but the public Rekor's verification path rejected
15
+ * it during the Day 5 smoke test (500 "error generating canonicalized
16
+ * entry"). See `docs/v0-acceptance.md` Day 5 evidence.
17
+ */
18
+ export declare const DSSE_VERSION = "DSSEv1";
19
+ export declare const IN_TOTO_PAYLOAD_TYPE = "application/vnd.in-toto+json";
20
+ export interface DsseSignature {
21
+ /** Single-base64 of the raw signature bytes. */
22
+ sig: string;
23
+ /** PEM-encoded SubjectPublicKeyInfo. */
24
+ publicKey: string;
25
+ /** Optional key identifier. Omit (don't pass empty string) when not set. */
26
+ keyid?: string;
27
+ }
28
+ export interface DsseEnvelope {
29
+ /** Media type of the payload (e.g. `application/vnd.in-toto+json`). */
30
+ payloadType: string;
31
+ /** Single-base64 of the raw payload bytes. */
32
+ payload: string;
33
+ signatures: DsseSignature[];
34
+ }
35
+ /**
36
+ * DSSE Pre-Authentication Encoding (PAE):
37
+ *
38
+ * "DSSEv1" SP LEN(type) SP type SP LEN(body) SP body
39
+ *
40
+ * Where SP is a single 0x20 space, LEN is the ASCII-decimal length of
41
+ * the following byte string.
42
+ */
43
+ export declare function pae(type: string, body: Uint8Array): Uint8Array;
44
+ export interface SignEnvelopeResult {
45
+ envelope: DsseEnvelope;
46
+ /** PEM of the ephemeral public key (also embedded in envelope.signatures[0].publicKey). */
47
+ publicKeyPem: string;
48
+ }
49
+ /**
50
+ * Generate an ephemeral ECDSA P-256 keypair, sign PAE(payloadType,
51
+ * payload), and return a DSSE envelope. The private key is discarded
52
+ * before return.
53
+ */
54
+ export declare function signEnvelope(payload: Uint8Array, payloadType: string): SignEnvelopeResult;
55
+ //# sourceMappingURL=dsse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dsse.d.ts","sourceRoot":"","sources":["../src/dsse.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,eAAO,MAAM,YAAY,WAAW,CAAC;AACrC,eAAO,MAAM,oBAAoB,iCAAiC,CAAC;AAEnE,MAAM,WAAW,aAAa;IAC5B,gDAAgD;IAChD,GAAG,EAAE,MAAM,CAAC;IACZ,wCAAwC;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,4EAA4E;IAC5E,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,uEAAuE;IACvE,WAAW,EAAE,MAAM,CAAC;IACpB,8CAA8C;IAC9C,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,aAAa,EAAE,CAAC;CAC7B;AAED;;;;;;;GAOG;AACH,wBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,UAAU,CAQ9D;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,YAAY,CAAC;IACvB,2FAA2F;IAC3F,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,GAAG,kBAAkB,CAqBzF"}
package/dist/dsse.js ADDED
@@ -0,0 +1,64 @@
1
+ /**
2
+ * DSSE (Dead Simple Signing Envelope) envelope builder.
3
+ *
4
+ * Per-binding ephemeral ECDSA P-256 key — the private key is discarded
5
+ * after signing. The DSSE signature is a Rekor schema requirement, not
6
+ * a trust mechanism. The actual authentication for passportsign comes
7
+ * from the zkPassport proof + GitHub gist evidence carried inside the
8
+ * statement's predicate, not from this signature.
9
+ *
10
+ * Spec: https://github.com/secure-systems-lab/dsse/blob/master/protocol.md
11
+ *
12
+ * Note on key algorithm choice: ECDSA P-256 over SHA-256 is what
13
+ * Rekor's public instance accepts for intoto v0.0.2 entries. Ed25519
14
+ * is in the DSSE spec but the public Rekor's verification path rejected
15
+ * it during the Day 5 smoke test (500 "error generating canonicalized
16
+ * entry"). See `docs/v0-acceptance.md` Day 5 evidence.
17
+ */
18
+ import { createSign, generateKeyPairSync } from 'node:crypto';
19
+ export const DSSE_VERSION = 'DSSEv1';
20
+ export const IN_TOTO_PAYLOAD_TYPE = 'application/vnd.in-toto+json';
21
+ /**
22
+ * DSSE Pre-Authentication Encoding (PAE):
23
+ *
24
+ * "DSSEv1" SP LEN(type) SP type SP LEN(body) SP body
25
+ *
26
+ * Where SP is a single 0x20 space, LEN is the ASCII-decimal length of
27
+ * the following byte string.
28
+ */
29
+ export function pae(type, body) {
30
+ const typeBytes = new TextEncoder().encode(type);
31
+ const prefix = `${DSSE_VERSION} ${typeBytes.length} ${type} ${body.length} `;
32
+ const prefixBytes = new TextEncoder().encode(prefix);
33
+ const out = new Uint8Array(prefixBytes.length + body.length);
34
+ out.set(prefixBytes);
35
+ out.set(body, prefixBytes.length);
36
+ return out;
37
+ }
38
+ /**
39
+ * Generate an ephemeral ECDSA P-256 keypair, sign PAE(payloadType,
40
+ * payload), and return a DSSE envelope. The private key is discarded
41
+ * before return.
42
+ */
43
+ export function signEnvelope(payload, payloadType) {
44
+ const { privateKey, publicKey } = generateKeyPairSync('ec', { namedCurve: 'P-256' });
45
+ const paeBytes = pae(payloadType, payload);
46
+ const signer = createSign('SHA256');
47
+ signer.update(Buffer.from(paeBytes));
48
+ const sigBuf = signer.sign(privateKey);
49
+ const publicKeyPem = publicKey.export({ type: 'spki', format: 'pem' });
50
+ return {
51
+ envelope: {
52
+ payloadType,
53
+ payload: Buffer.from(payload).toString('base64'),
54
+ signatures: [
55
+ {
56
+ sig: sigBuf.toString('base64'),
57
+ publicKey: publicKeyPem,
58
+ },
59
+ ],
60
+ },
61
+ publicKeyPem,
62
+ };
63
+ }
64
+ //# sourceMappingURL=dsse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dsse.js","sourceRoot":"","sources":["../src/dsse.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAE9D,MAAM,CAAC,MAAM,YAAY,GAAG,QAAQ,CAAC;AACrC,MAAM,CAAC,MAAM,oBAAoB,GAAG,8BAA8B,CAAC;AAmBnE;;;;;;;GAOG;AACH,MAAM,UAAU,GAAG,CAAC,IAAY,EAAE,IAAgB;IAChD,MAAM,SAAS,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACjD,MAAM,MAAM,GAAG,GAAG,YAAY,IAAI,SAAS,CAAC,MAAM,IAAI,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;IAC7E,MAAM,WAAW,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACrD,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,WAAW,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;IAC7D,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IACrB,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAClC,OAAO,GAAG,CAAC;AACb,CAAC;AAQD;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,OAAmB,EAAE,WAAmB;IACnE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,mBAAmB,CAAC,IAAI,EAAE,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC,CAAC;IACrF,MAAM,QAAQ,GAAG,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IACpC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;IACrC,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACvC,MAAM,YAAY,GAAG,SAAS,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAW,CAAC;IAEjF,OAAO;QACL,QAAQ,EAAE;YACR,WAAW;YACX,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC;YAChD,UAAU,EAAE;gBACV;oBACE,GAAG,EAAE,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC;oBAC9B,SAAS,EAAE,YAAY;iBACxB;aACF;SACF;QACD,YAAY;KACb,CAAC;AACJ,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * §4 error vocabulary — the set of failure codes a bind/verify call can
3
+ * surface to a caller. Verbatim from `docs/passportsign.md` §4.
4
+ *
5
+ * Callers should `catch` `PassportsignError` and branch on `.code`. The
6
+ * `cause` field carries the underlying error (HTTP response body, SDK
7
+ * error, etc.) for logging — never for client display, since it may
8
+ * include identifying data.
9
+ */
10
+ export declare const ERROR_CODES: readonly ["username_invalid", "binding_pending_expired", "gist_not_found", "gist_wrong_content", "gist_wrong_owner", "gist_predates_init", "proof_invalid", "proof_scope_mismatch", "proof_missing_personhood", "log_submission_failed", "internal_error"];
11
+ export type ErrorCode = (typeof ERROR_CODES)[number];
12
+ export declare class PassportsignError extends Error {
13
+ readonly code: ErrorCode;
14
+ readonly cause: unknown;
15
+ constructor(code: ErrorCode, message: string, cause?: unknown);
16
+ }
17
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,eAAO,MAAM,WAAW,4PAYd,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAErD,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,SAAkB,KAAK,EAAE,OAAO,CAAC;gBAErB,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;CAM9D"}
package/dist/errors.js ADDED
@@ -0,0 +1,33 @@
1
+ /**
2
+ * §4 error vocabulary — the set of failure codes a bind/verify call can
3
+ * surface to a caller. Verbatim from `docs/passportsign.md` §4.
4
+ *
5
+ * Callers should `catch` `PassportsignError` and branch on `.code`. The
6
+ * `cause` field carries the underlying error (HTTP response body, SDK
7
+ * error, etc.) for logging — never for client display, since it may
8
+ * include identifying data.
9
+ */
10
+ export const ERROR_CODES = [
11
+ 'username_invalid',
12
+ 'binding_pending_expired',
13
+ 'gist_not_found',
14
+ 'gist_wrong_content',
15
+ 'gist_wrong_owner',
16
+ 'gist_predates_init',
17
+ 'proof_invalid',
18
+ 'proof_scope_mismatch',
19
+ 'proof_missing_personhood',
20
+ 'log_submission_failed',
21
+ 'internal_error',
22
+ ];
23
+ export class PassportsignError extends Error {
24
+ code;
25
+ cause;
26
+ constructor(code, message, cause) {
27
+ super(message);
28
+ this.name = 'PassportsignError';
29
+ this.code = code;
30
+ this.cause = cause;
31
+ }
32
+ }
33
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,kBAAkB;IAClB,yBAAyB;IACzB,gBAAgB;IAChB,oBAAoB;IACpB,kBAAkB;IAClB,oBAAoB;IACpB,eAAe;IACf,sBAAsB;IACtB,0BAA0B;IAC1B,uBAAuB;IACvB,gBAAgB;CACR,CAAC;AAIX,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IACjC,IAAI,CAAY;IACP,KAAK,CAAU;IAEjC,YAAY,IAAe,EAAE,OAAe,EAAE,KAAe;QAC3D,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;QAChC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;CACF"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * GitHub gist control check per spec §3 step 5 and §14 "The gist control check."
3
+ *
4
+ * The honest semantic claim is: at the moment we checked, the named user
5
+ * controlled a public gist with the expected filename and content. We
6
+ * capture `html_url`, `updated_at`, and a SHA-256 of the content so the
7
+ * evidence is independently re-checkable later (e.g. via the Wayback
8
+ * Machine).
9
+ *
10
+ * The optional `token` is **purely for rate-limit headroom** — it
11
+ * carries zero special access. Unauth'd: 60 req/hr; with token: 5000.
12
+ */
13
+ export interface GistEvidence {
14
+ url: string;
15
+ content_sha256: string;
16
+ updated_at: string;
17
+ }
18
+ export interface CheckGistOptions {
19
+ username: string;
20
+ expected_filename: string;
21
+ expected_content: string;
22
+ not_before: Date;
23
+ token?: string;
24
+ fetch?: typeof fetch;
25
+ baseUrl?: string;
26
+ }
27
+ export declare function checkGistControl(opts: CheckGistOptions): Promise<GistEvidence>;
28
+ //# sourceMappingURL=github.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github.d.ts","sourceRoot":"","sources":["../src/github.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,IAAI,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AA+BD,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,YAAY,CAAC,CAsIpF"}
package/dist/github.js ADDED
@@ -0,0 +1,113 @@
1
+ /**
2
+ * GitHub gist control check per spec §3 step 5 and §14 "The gist control check."
3
+ *
4
+ * The honest semantic claim is: at the moment we checked, the named user
5
+ * controlled a public gist with the expected filename and content. We
6
+ * capture `html_url`, `updated_at`, and a SHA-256 of the content so the
7
+ * evidence is independently re-checkable later (e.g. via the Wayback
8
+ * Machine).
9
+ *
10
+ * The optional `token` is **purely for rate-limit headroom** — it
11
+ * carries zero special access. Unauth'd: 60 req/hr; with token: 5000.
12
+ */
13
+ import { createHash } from 'node:crypto';
14
+ import { PassportsignError } from './errors.js';
15
+ const DEFAULT_BASE_URL = 'https://api.github.com';
16
+ const GIST_LIST_PER_PAGE = 100;
17
+ function sha256Hex(content) {
18
+ return createHash('sha256').update(content, 'utf8').digest('hex');
19
+ }
20
+ function authHeaders(token) {
21
+ return {
22
+ Accept: 'application/vnd.github+json',
23
+ 'X-GitHub-Api-Version': '2022-11-28',
24
+ 'User-Agent': 'passportsign-cli',
25
+ ...(token ? { Authorization: `Bearer ${token}` } : {}),
26
+ };
27
+ }
28
+ export async function checkGistControl(opts) {
29
+ const fetchImpl = opts.fetch ?? globalThis.fetch;
30
+ const baseUrl = opts.baseUrl ?? DEFAULT_BASE_URL;
31
+ const headers = authHeaders(opts.token);
32
+ if (opts.username.length === 0) {
33
+ throw new PassportsignError('username_invalid', 'username must be non-empty');
34
+ }
35
+ // Step 1: list the user's gists, filter by filename.
36
+ const listUrl = `${baseUrl}/users/${encodeURIComponent(opts.username)}/gists?per_page=${GIST_LIST_PER_PAGE}`;
37
+ let listResponse;
38
+ try {
39
+ listResponse = await fetchImpl(listUrl, { headers });
40
+ }
41
+ catch (err) {
42
+ throw new PassportsignError('internal_error', `GitHub list-gists request failed: ${err instanceof Error ? err.message : String(err)}`, err);
43
+ }
44
+ if (listResponse.status === 404) {
45
+ throw new PassportsignError('username_invalid', `GitHub user '${opts.username}' not found`);
46
+ }
47
+ if (!listResponse.ok) {
48
+ throw new PassportsignError('internal_error', `GitHub list-gists returned HTTP ${listResponse.status}`);
49
+ }
50
+ let listBody;
51
+ try {
52
+ listBody = await listResponse.json();
53
+ }
54
+ catch (err) {
55
+ throw new PassportsignError('internal_error', 'GitHub list-gists returned non-JSON', err);
56
+ }
57
+ if (!Array.isArray(listBody)) {
58
+ throw new PassportsignError('internal_error', 'GitHub list-gists did not return an array');
59
+ }
60
+ const matches = listBody
61
+ .filter((g) => g && typeof g === 'object' && opts.expected_filename in (g.files ?? {}))
62
+ .sort((a, b) => (a.updated_at < b.updated_at ? 1 : -1));
63
+ const match = matches[0];
64
+ if (!match) {
65
+ throw new PassportsignError('gist_not_found', `no public gist owned by '${opts.username}' contains file '${opts.expected_filename}'`);
66
+ }
67
+ // Step 2: re-fetch the gist by id to get the full content.
68
+ let detailResponse;
69
+ try {
70
+ detailResponse = await fetchImpl(`${baseUrl}/gists/${match.id}`, { headers });
71
+ }
72
+ catch (err) {
73
+ throw new PassportsignError('internal_error', `GitHub get-gist request failed: ${err instanceof Error ? err.message : String(err)}`, err);
74
+ }
75
+ if (!detailResponse.ok) {
76
+ throw new PassportsignError('internal_error', `GitHub get-gist returned HTTP ${detailResponse.status}`);
77
+ }
78
+ let detail;
79
+ try {
80
+ detail = (await detailResponse.json());
81
+ }
82
+ catch (err) {
83
+ throw new PassportsignError('internal_error', 'GitHub get-gist returned non-JSON', err);
84
+ }
85
+ // Step 3: owner check (case-insensitive per spec §10 row 7).
86
+ const ownerLogin = detail.owner?.login;
87
+ if (!ownerLogin || ownerLogin.toLowerCase() !== opts.username.toLowerCase()) {
88
+ throw new PassportsignError('gist_wrong_owner', `gist ${match.id} owner '${ownerLogin ?? 'unknown'}' does not match expected '${opts.username}'`);
89
+ }
90
+ // Step 4: content exact match.
91
+ const file = (detail.files ?? {})[opts.expected_filename];
92
+ const content = file?.content;
93
+ if (typeof content !== 'string') {
94
+ throw new PassportsignError('gist_wrong_content', `gist ${match.id} has no readable content for '${opts.expected_filename}'`);
95
+ }
96
+ if (content !== opts.expected_content) {
97
+ throw new PassportsignError('gist_wrong_content', `gist ${match.id} content does not exactly match the expected nonce`);
98
+ }
99
+ // Step 5: freshness — gist's updated_at must be at/after init.
100
+ const updatedAtMs = Date.parse(detail.updated_at);
101
+ if (Number.isNaN(updatedAtMs)) {
102
+ throw new PassportsignError('internal_error', `gist ${match.id} updated_at is unparseable: ${detail.updated_at}`);
103
+ }
104
+ if (updatedAtMs < opts.not_before.getTime()) {
105
+ throw new PassportsignError('gist_predates_init', `gist ${match.id} updated_at (${detail.updated_at}) predates init (${opts.not_before.toISOString()})`);
106
+ }
107
+ return {
108
+ url: detail.html_url,
109
+ content_sha256: sha256Hex(content),
110
+ updated_at: detail.updated_at,
111
+ };
112
+ }
113
+ //# sourceMappingURL=github.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github.js","sourceRoot":"","sources":["../src/github.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Public API of @passportsign/core.
3
+ *
4
+ * Day 1-2: canonical JCS + in-toto statement + bundle format.
5
+ * Day 3-4: §4 error vocabulary + nonce + GitHub gist check +
6
+ * SQLite cache + bind orchestrator (no Rekor yet).
7
+ */
8
+ export { canonicalize, canonicalSha256Hex, } from './canonical.js';
9
+ export { IN_TOTO_STATEMENT_TYPE, PASSPORTSIGN_PREDICATE_TYPE, buildStatement, type BuildStatementInput, type DisclosureLevel, type PassportsignPredicate, type PassportsignStatement, } from './statement.js';
10
+ export { BUNDLE_FORMAT_VERSION, BundleValidationError, readBundle, validateBundle, writeBundle, type PassportsignBundle, type RekorBundleFields, } from './bundle.js';
11
+ export { ERROR_CODES, PassportsignError, type ErrorCode, } from './errors.js';
12
+ export { NONCE_BYTES, NONCE_BASE32_LENGTH, base32Encode, generateNonce, } from './nonce.js';
13
+ export { checkGistControl, type CheckGistOptions, type GistEvidence, } from './github.js';
14
+ export { prepareBinding, type PrepareBindingDeps, type PrepareBindingInit, type PrepareBindingInput, type PreparedBinding, } from './bind.js';
15
+ export { DSSE_VERSION, IN_TOTO_PAYLOAD_TYPE, pae, signEnvelope, type DsseEnvelope, type DsseSignature, type SignEnvelopeResult, } from './dsse.js';
16
+ export { DEFAULT_REKOR_BASE_URL, PublicSigstoreRekorClient, buildIntotoEntryBody, type InclusionProof, type PublicSigstoreRekorClientOptions, type RekorClient, type RekorEntryResponse, } from './log/rekor.js';
17
+ export { submitBinding, type SubmitBindingDeps, type SubmitBindingResult, } from './submit.js';
18
+ export { hashLeaf, hashPair, verifyConsistency, verifyInclusion, } from './merkle.js';
19
+ export { packSdkPayload, unpackSdkPayload, type PackedSdkPayload, type SdkPayload, } from './sdk-payload.js';
20
+ export { renderBadgeMarkdown, renderBadgeSvg, type BadgeInput, } from './badge.js';
21
+ export { verifyBundle, type BundleVerifyResult, type CheckResult, type SdkVerifier, type SdkVerifyInput, type SdkVerifyResult, type VerifyBundleDeps, } from './verifier.js';
22
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,YAAY,EACZ,kBAAkB,GACnB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,sBAAsB,EACtB,2BAA2B,EAC3B,cAAc,EACd,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,GAC3B,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACrB,UAAU,EACV,cAAc,EACd,WAAW,EACX,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,GACvB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,WAAW,EACX,iBAAiB,EACjB,KAAK,SAAS,GACf,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,WAAW,EACX,mBAAmB,EACnB,YAAY,EACZ,aAAa,GACd,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,gBAAgB,EAChB,KAAK,gBAAgB,EACrB,KAAK,YAAY,GAClB,MAAM,aAAa,CAAC;AAQrB,OAAO,EACL,cAAc,EACd,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,eAAe,GACrB,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,YAAY,EACZ,oBAAoB,EACpB,GAAG,EACH,YAAY,EACZ,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,kBAAkB,GACxB,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,sBAAsB,EACtB,yBAAyB,EACzB,oBAAoB,EACpB,KAAK,cAAc,EACnB,KAAK,gCAAgC,EACrC,KAAK,WAAW,EAChB,KAAK,kBAAkB,GACxB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,aAAa,EACb,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,GACzB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,QAAQ,EACR,QAAQ,EACR,iBAAiB,EACjB,eAAe,GAChB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,KAAK,gBAAgB,EACrB,KAAK,UAAU,GAChB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,KAAK,UAAU,GAChB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,YAAY,EACZ,KAAK,kBAAkB,EACvB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,gBAAgB,GACtB,MAAM,eAAe,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Public API of @passportsign/core.
3
+ *
4
+ * Day 1-2: canonical JCS + in-toto statement + bundle format.
5
+ * Day 3-4: §4 error vocabulary + nonce + GitHub gist check +
6
+ * SQLite cache + bind orchestrator (no Rekor yet).
7
+ */
8
+ export { canonicalize, canonicalSha256Hex, } from './canonical.js';
9
+ export { IN_TOTO_STATEMENT_TYPE, PASSPORTSIGN_PREDICATE_TYPE, buildStatement, } from './statement.js';
10
+ export { BUNDLE_FORMAT_VERSION, BundleValidationError, readBundle, validateBundle, writeBundle, } from './bundle.js';
11
+ export { ERROR_CODES, PassportsignError, } from './errors.js';
12
+ export { NONCE_BYTES, NONCE_BASE32_LENGTH, base32Encode, generateNonce, } from './nonce.js';
13
+ export { checkGistControl, } from './github.js';
14
+ // SQLite cache is intentionally not re-exported from the main entry —
15
+ // `node:sqlite` doesn't bundle cleanly (esbuild strips the `node:` prefix
16
+ // and there's no public `sqlite` npm package by that name). Consumers
17
+ // who need it should import from `@passportsign/core/storage/sqlite`
18
+ // directly. The v0 CLI doesn't use the cache; rebuild is v1 work.
19
+ export { prepareBinding, } from './bind.js';
20
+ export { DSSE_VERSION, IN_TOTO_PAYLOAD_TYPE, pae, signEnvelope, } from './dsse.js';
21
+ export { DEFAULT_REKOR_BASE_URL, PublicSigstoreRekorClient, buildIntotoEntryBody, } from './log/rekor.js';
22
+ export { submitBinding, } from './submit.js';
23
+ export { hashLeaf, hashPair, verifyConsistency, verifyInclusion, } from './merkle.js';
24
+ export { packSdkPayload, unpackSdkPayload, } from './sdk-payload.js';
25
+ export { renderBadgeMarkdown, renderBadgeSvg, } from './badge.js';
26
+ export { verifyBundle, } from './verifier.js';
27
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,YAAY,EACZ,kBAAkB,GACnB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,sBAAsB,EACtB,2BAA2B,EAC3B,cAAc,GAKf,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACrB,UAAU,EACV,cAAc,EACd,WAAW,GAGZ,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,WAAW,EACX,iBAAiB,GAElB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,WAAW,EACX,mBAAmB,EACnB,YAAY,EACZ,aAAa,GACd,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,gBAAgB,GAGjB,MAAM,aAAa,CAAC;AAErB,sEAAsE;AACtE,0EAA0E;AAC1E,sEAAsE;AACtE,qEAAqE;AACrE,kEAAkE;AAElE,OAAO,EACL,cAAc,GAKf,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,YAAY,EACZ,oBAAoB,EACpB,GAAG,EACH,YAAY,GAIb,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,sBAAsB,EACtB,yBAAyB,EACzB,oBAAoB,GAKrB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,aAAa,GAGd,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,QAAQ,EACR,QAAQ,EACR,iBAAiB,EACjB,eAAe,GAChB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,cAAc,EACd,gBAAgB,GAGjB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,mBAAmB,EACnB,cAAc,GAEf,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,YAAY,GAOb,MAAM,eAAe,CAAC"}