@forestrie/forestrie-cli 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.
Files changed (124) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +425 -0
  3. package/TRUST-MODEL.md +8 -0
  4. package/dist/cli.js +33811 -0
  5. package/dist/decode-receipt.d.ts +19 -0
  6. package/dist/decode-receipt.d.ts.map +1 -0
  7. package/dist/decode-receipt.js +19 -0
  8. package/dist/decode-receipt.js.map +1 -0
  9. package/dist/index.d.ts +11 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +11 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/lib/decode-receipt-cbor.d.ts +26 -0
  14. package/dist/lib/decode-receipt-cbor.d.ts.map +1 -0
  15. package/dist/lib/decode-receipt-cbor.js +182 -0
  16. package/dist/lib/decode-receipt-cbor.js.map +1 -0
  17. package/dist/lib/decode-receipt-decode.d.ts +103 -0
  18. package/dist/lib/decode-receipt-decode.d.ts.map +1 -0
  19. package/dist/lib/decode-receipt-decode.js +237 -0
  20. package/dist/lib/decode-receipt-decode.js.map +1 -0
  21. package/dist/lib/decode-receipt-labels.d.ts +54 -0
  22. package/dist/lib/decode-receipt-labels.d.ts.map +1 -0
  23. package/dist/lib/decode-receipt-labels.js +117 -0
  24. package/dist/lib/decode-receipt-labels.js.map +1 -0
  25. package/dist/lib/decode-receipt-render.d.ts +11 -0
  26. package/dist/lib/decode-receipt-render.d.ts.map +1 -0
  27. package/dist/lib/decode-receipt-render.js +242 -0
  28. package/dist/lib/decode-receipt-render.js.map +1 -0
  29. package/package.json +83 -0
  30. package/src/cli.ts +5 -0
  31. package/src/command.ts +51 -0
  32. package/src/commands/admin-onboard-token.ts +51 -0
  33. package/src/commands/admin.ts +20 -0
  34. package/src/commands/complete-grant.ts +41 -0
  35. package/src/commands/create-consistency-proof.ts +44 -0
  36. package/src/commands/create-log.ts +95 -0
  37. package/src/commands/decode-receipt.ts +20 -0
  38. package/src/commands/delegate.ts +55 -0
  39. package/src/commands/deploy.ts +72 -0
  40. package/src/commands/fetch-accumulator.ts +49 -0
  41. package/src/commands/onboard-genesis.ts +70 -0
  42. package/src/commands/onboard-request.ts +59 -0
  43. package/src/commands/register-grant.ts +74 -0
  44. package/src/commands/register.ts +54 -0
  45. package/src/commands/resolve-receipt.ts +101 -0
  46. package/src/commands/sign-statement.ts +53 -0
  47. package/src/commands/verify-grant.ts +89 -0
  48. package/src/commands/verify.ts +92 -0
  49. package/src/commoncli.ts +34 -0
  50. package/src/decode-receipt.ts +56 -0
  51. package/src/index.ts +10 -0
  52. package/src/lib/bytes.ts +7 -0
  53. package/src/lib/checkpoint-provider.ts +297 -0
  54. package/src/lib/complete-grant-derive.ts +237 -0
  55. package/src/lib/consistency-proof.ts +271 -0
  56. package/src/lib/create-log-build.ts +168 -0
  57. package/src/lib/create-log-prepare.ts +75 -0
  58. package/src/lib/create-receipt-chain-verify.ts +267 -0
  59. package/src/lib/create-receipt-derive.ts +208 -0
  60. package/src/lib/create-receipt-inputs.ts +79 -0
  61. package/src/lib/decode-checkpoint-calldata.ts +188 -0
  62. package/src/lib/decode-receipt-cbor.ts +202 -0
  63. package/src/lib/decode-receipt-decode.ts +333 -0
  64. package/src/lib/decode-receipt-labels.ts +132 -0
  65. package/src/lib/decode-receipt-render.ts +284 -0
  66. package/src/lib/delegate-flow.ts +289 -0
  67. package/src/lib/delegate-voucher.ts +122 -0
  68. package/src/lib/deploy-artifact.ts +79 -0
  69. package/src/lib/deploy-bootstrap.ts +100 -0
  70. package/src/lib/deploy-flow.ts +184 -0
  71. package/src/lib/deploy-genesis-log-id.ts +29 -0
  72. package/src/lib/deploy-rpc.ts +40 -0
  73. package/src/lib/deployment-record.ts +65 -0
  74. package/src/lib/fsio.ts +91 -0
  75. package/src/lib/grant-flags-local.ts +19 -0
  76. package/src/lib/onboard-attestation.ts +120 -0
  77. package/src/lib/onboard-genesis-body.ts +94 -0
  78. package/src/lib/openssl-error-queue.ts +56 -0
  79. package/src/lib/register-flow.ts +292 -0
  80. package/src/lib/register-grant-build.ts +173 -0
  81. package/src/lib/register-grant-complete.ts +47 -0
  82. package/src/lib/register-grant-flow.ts +258 -0
  83. package/src/lib/resolve-receipt-freshen.ts +221 -0
  84. package/src/lib/sign-statement-build.ts +117 -0
  85. package/src/lib/sign-statement-key.ts +145 -0
  86. package/src/lib/verify-anchored.ts +326 -0
  87. package/src/lib/verify-checkpoint-chain.ts +160 -0
  88. package/src/lib/verify-eventscan.ts +214 -0
  89. package/src/lib/verify-inputs.ts +143 -0
  90. package/src/lib/verify-known-accumulator.ts +161 -0
  91. package/src/lib/verify-report.ts +265 -0
  92. package/src/lib/x402-payment.ts +115 -0
  93. package/src/main/admin-onboard-token.ts +216 -0
  94. package/src/main/complete-grant.ts +265 -0
  95. package/src/main/create-consistency-proof.ts +83 -0
  96. package/src/main/create-log.ts +347 -0
  97. package/src/main/create-receipt.ts +763 -0
  98. package/src/main/decode-receipt.ts +72 -0
  99. package/src/main/delegate.ts +141 -0
  100. package/src/main/deploy.ts +273 -0
  101. package/src/main/fetch-accumulator.ts +181 -0
  102. package/src/main/not-implemented.ts +43 -0
  103. package/src/main/onboard-genesis.ts +192 -0
  104. package/src/main/onboard-request.ts +333 -0
  105. package/src/main/register-grant.ts +270 -0
  106. package/src/main/register.ts +243 -0
  107. package/src/main/sign-statement.ts +168 -0
  108. package/src/main/verify.ts +767 -0
  109. package/src/options/admin-onboard-token.ts +48 -0
  110. package/src/options/common.ts +69 -0
  111. package/src/options/complete-grant.ts +40 -0
  112. package/src/options/create-consistency-proof.ts +63 -0
  113. package/src/options/create-log.ts +99 -0
  114. package/src/options/create-receipt.ts +243 -0
  115. package/src/options/decode-receipt.ts +25 -0
  116. package/src/options/delegate.ts +93 -0
  117. package/src/options/deploy.ts +105 -0
  118. package/src/options/fetch-accumulator.ts +62 -0
  119. package/src/options/onboard-genesis.ts +74 -0
  120. package/src/options/onboard-request.ts +57 -0
  121. package/src/options/register-grant.ts +72 -0
  122. package/src/options/register.ts +71 -0
  123. package/src/options/sign-statement.ts +64 -0
  124. package/src/options/verify.ts +250 -0
@@ -0,0 +1,54 @@
1
+ import { defineCommandRunner, defineForestrieCommand } from "../commoncli.js";
2
+ import { runRegister } from "../main/register.js";
3
+ import { parseRegisterOptions } from "../options/register.js";
4
+
5
+ export default defineForestrieCommand({
6
+ meta: {
7
+ name: "register",
8
+ description:
9
+ "Register a signed statement via SCRAPI and download the receipt (any SCRAPI client, plain COSE Sign1) [FOR-342]",
10
+ },
11
+ args: {
12
+ "base-url": {
13
+ type: "string",
14
+ description:
15
+ "SCRAPI origin, no trailing slash (env FORESTRIE_BASE_URL)",
16
+ valueHint: "url",
17
+ },
18
+ "log-id": {
19
+ type: "string",
20
+ description: "Target log id (UUID)",
21
+ valueHint: "uuid",
22
+ required: true,
23
+ },
24
+ statement: {
25
+ type: "string",
26
+ description:
27
+ "COSE Sign1 signed statement file ('-' or omitted: read stdin)",
28
+ valueHint: "path",
29
+ },
30
+ "grant-b64": {
31
+ type: "string",
32
+ description:
33
+ "Authorization: Forestrie-Grant bearer credential, base64 (env GRANT_B64)",
34
+ valueHint: "base64",
35
+ },
36
+ out: {
37
+ type: "string",
38
+ description: "Write the receipt bytes to this path",
39
+ valueHint: "path",
40
+ },
41
+ timeout: {
42
+ type: "string",
43
+ description: "Overall receipt wait budget in seconds (default 60)",
44
+ valueHint: "seconds",
45
+ },
46
+ "poll-interval": {
47
+ type: "string",
48
+ description:
49
+ "Pacing between registration/receipt polls in seconds (default 1; Retry-After wins when longer)",
50
+ valueHint: "seconds",
51
+ },
52
+ },
53
+ run: defineCommandRunner(parseRegisterOptions, runRegister),
54
+ });
@@ -0,0 +1,101 @@
1
+ import { defineCommandRunner, defineForestrieCommand } from "../commoncli.js";
2
+ import { runCreateReceipt } from "../main/create-receipt.js";
3
+ import { parseCreateReceiptOptions } from "../options/create-receipt.js";
4
+
5
+ export default defineForestrieCommand({
6
+ meta: {
7
+ name: "resolve-receipt",
8
+ description:
9
+ "Produce or freshen a COSE receipt (SCRAPI §2.4) — source by flags: --massif (tiles), --receipt + --checkpoint-chain (.sth freshen), or --receipt + --rpc-url/--univocity/--log-id + --checkpoint (calldata freshen). Freshen re-anchors a stale receipt to the current accumulator; the trust posture is set at verify (https://github.com/forestrie/protocol/blob/main/spec/receipt-trust-model.md) [FOR-345/FOR-418]. Alias: create-receipt.",
10
+ },
11
+ args: {
12
+ // --- tiles source (--massif) ---
13
+ massif: {
14
+ type: "string",
15
+ description: "Massif .log blob holding the leaf and its proof nodes (tiles source)",
16
+ valueHint: "path",
17
+ },
18
+ "mmr-index": {
19
+ type: "string",
20
+ description:
21
+ "MMR index of the leaf to prove (tiles source; exactly one of --mmr-index / --entry-id)",
22
+ valueHint: "n",
23
+ },
24
+ checkpoint: {
25
+ type: "string",
26
+ description:
27
+ "Checkpoint (.sth) with pre-signed peak receipts (tiles source, offline mode)",
28
+ valueHint: "path",
29
+ },
30
+ univocity: {
31
+ type: "string",
32
+ description:
33
+ "ImutableUnivocity contract address (tiles source, chain-anchored; needs --log-id and --rpc-url)",
34
+ valueHint: "0x…",
35
+ },
36
+ "log-id": {
37
+ type: "string",
38
+ description: "Log id for the on-chain accumulator read (chain-anchored mode)",
39
+ valueHint: "uuid",
40
+ },
41
+ "rpc-url": {
42
+ type: "string",
43
+ description: "JSON-RPC endpoint (env RPC_URL; chain-anchored mode)",
44
+ valueHint: "url",
45
+ },
46
+ // --- freshen source (--receipt + a tile-free chain) ---
47
+ receipt: {
48
+ type: "string",
49
+ description: "Stale receipt to freshen tile-free (freshen source)",
50
+ valueHint: "path",
51
+ },
52
+ "checkpoint-chain": {
53
+ type: "string",
54
+ description:
55
+ "Retained .sth checkpoint chain — a directory or comma-separated files (freshen source; the freshened receipt is emitted under the chain's own tail checkpoint)",
56
+ valueHint: "dir|files",
57
+ },
58
+ "committed-grant": {
59
+ type: "string",
60
+ description:
61
+ "Committed grant, base64 — recomputes the leaf value (freshen source)",
62
+ valueHint: "b64",
63
+ },
64
+ "committed-grant-file": {
65
+ type: "string",
66
+ description:
67
+ "Committed grant CBOR file — recomputes the leaf value (freshen; needs --entry-id)",
68
+ valueHint: "path",
69
+ },
70
+ payload: {
71
+ type: "string",
72
+ description:
73
+ "Registered statement payload — the leaf ContentHash (freshen statement receipts; alternative to --committed-grant, needs --entry-id)",
74
+ valueHint: "path",
75
+ },
76
+ // --- shared ---
77
+ "entry-id": {
78
+ type: "string",
79
+ description:
80
+ "Permanent SCRAPI entry id (leaf addressing for tiles; idtimestamp for freshen), 32 hex chars",
81
+ valueHint: "hex",
82
+ },
83
+ out: {
84
+ type: "string",
85
+ description: "Receipt output path (default: stdout)",
86
+ valueHint: "path",
87
+ },
88
+ "in-place": {
89
+ type: "boolean",
90
+ description:
91
+ "Rewrite the --receipt file with the freshened receipt (freshen only; mutually exclusive with --out)",
92
+ },
93
+ "known-accumulator": {
94
+ type: "string",
95
+ description:
96
+ "Trusted accumulator snapshot (fetch-accumulator output) — binds the freshened state to a trusted chain read, failing closed on mismatch (freshen only; anchors freshness, not signer provenance — https://github.com/forestrie/protocol/blob/main/spec/receipt-trust-model.md)",
97
+ valueHint: "path",
98
+ },
99
+ },
100
+ run: defineCommandRunner(parseCreateReceiptOptions, runCreateReceipt),
101
+ });
@@ -0,0 +1,53 @@
1
+ import { defineCommandRunner, defineForestrieCommand } from "../commoncli.js";
2
+ import { runSignStatement } from "../main/sign-statement.js";
3
+ import { parseSignStatementOptions } from "../options/sign-statement.js";
4
+
5
+ export default defineForestrieCommand({
6
+ meta: {
7
+ name: "sign-statement",
8
+ description:
9
+ "Produce a SCITT signed statement: plain COSE Sign1 (ES256) with alg, content type, kid and CWT claims (iss/sub, label 15) all in the protected header [FOR-341, FOR-371]",
10
+ },
11
+ args: {
12
+ key: {
13
+ type: "string",
14
+ description: "ES256 P-256 private signing key (PEM or JWK file)",
15
+ valueHint: "path",
16
+ required: true,
17
+ },
18
+ payload: {
19
+ type: "string",
20
+ description: "Payload file to sign ('-' reads stdin)",
21
+ valueHint: "path",
22
+ required: true,
23
+ },
24
+ "content-type": {
25
+ type: "string",
26
+ description: "Payload content type (protected COSE header, label 3)",
27
+ default: "application/json",
28
+ },
29
+ iss: {
30
+ type: "string",
31
+ description:
32
+ "Issuer (CWT claim 1, protected label 15): a StringOrURI, or 'ckt' for the RFC 9679 key-thumbprint URI (default: hex kid)",
33
+ },
34
+ sub: {
35
+ type: "string",
36
+ description:
37
+ "Subject (CWT claim 2, protected label 15): what the statement speaks about (default: sha-256:<hex> of the payload)",
38
+ valueHint: "string-or-uri",
39
+ },
40
+ iat: {
41
+ type: "string",
42
+ description:
43
+ "Issued-at (CWT claim 6): unix seconds or 'now' (default: omitted, keeping output deterministic)",
44
+ valueHint: "now|seconds",
45
+ },
46
+ out: {
47
+ type: "string",
48
+ description: "Signed statement output path (default: stdout)",
49
+ valueHint: "path",
50
+ },
51
+ },
52
+ run: defineCommandRunner(parseSignStatementOptions, runSignStatement),
53
+ });
@@ -0,0 +1,89 @@
1
+ import { defineCommandRunner, defineForestrieCommand } from "../commoncli.js";
2
+ import { runVerifyGrant } from "../main/verify.js";
3
+ import { parseVerifyGrantOptions } from "../options/verify.js";
4
+
5
+ export default defineForestrieCommand({
6
+ meta: {
7
+ name: "verify-grant",
8
+ description:
9
+ "Verify a forestrie authority/grant receipt offline. A thin wrapper over `verify`: it derives the grant commitment preimage from a structured grant and verifies it as the leaf payload. The receipt is a standard COSE Receipt; only the payload is forestrie-specific (matches the on-chain univocity accumulator) [FOR-347]",
10
+ },
11
+ args: {
12
+ genesis: {
13
+ type: "string",
14
+ description:
15
+ "Cached public genesis (genesis.cbor) — genesis-derived offline trust root (or supply --known-log-key instead)",
16
+ valueHint: "path",
17
+ },
18
+ "known-log-key": {
19
+ type: "string",
20
+ description:
21
+ "Caller-known log OWNER key (the delegation issuer), base64 x||y (64 bytes) (env KNOWN_LOG_KEY). Offline signer-provenance anchor that replaces --genesis; asserts (does not prove) the key-to-log binding — --genesis derives it from the grant chain, while the accumulator anchors (--known-accumulator / --rpc-url) supply split-view (freshness is a weaker, separate axis bearing only on coverage). See https://github.com/forestrie/protocol/blob/main/spec/receipt-trust-model.md",
22
+ valueHint: "base64",
23
+ },
24
+ receipt: {
25
+ type: "string",
26
+ description: "COSE receipt file to verify",
27
+ valueHint: "path",
28
+ required: true,
29
+ },
30
+ "committed-grant": {
31
+ type: "string",
32
+ description:
33
+ "Grant committed at the receipt's leaf, base64 (env GRANT_B64); or use --committed-grant-file + --entry-id",
34
+ valueHint: "base64",
35
+ },
36
+ "committed-grant-file": {
37
+ type: "string",
38
+ description: "Grant CBOR file (alternative to --committed-grant)",
39
+ valueHint: "path",
40
+ },
41
+ "entry-id": {
42
+ type: "string",
43
+ description: "Entry id within the grant CBOR (with --committed-grant-file)",
44
+ valueHint: "id",
45
+ },
46
+ univocity: {
47
+ type: "string",
48
+ description:
49
+ "ImutableUnivocity contract address — enables the chain-anchored check (with --log-id and --rpc-url)",
50
+ valueHint: "address",
51
+ },
52
+ "log-id": {
53
+ type: "string",
54
+ description: "Log id (UUID or hex) for the on-chain accumulator read",
55
+ valueHint: "uuid",
56
+ },
57
+ "rpc-url": {
58
+ type: "string",
59
+ description:
60
+ "JSON-RPC endpoint for the chain-anchored check (default: ${env} → RPC_URL)",
61
+ valueHint: "url",
62
+ },
63
+ "known-accumulator": {
64
+ type: "string",
65
+ description:
66
+ "Cached on-chain accumulator snapshot (CBOR from `forestrie fetch-accumulator`) — the chain-anchored check fully offline, no --rpc-url. Never source it unauthenticated from the log operator's tile store (that re-internalises operator trust). Older receipts extend to a newer snapshot via --massif; newer receipts fail closed",
67
+ valueHint: "path",
68
+ },
69
+ massif: {
70
+ type: "string",
71
+ description:
72
+ "Local massif blob — enables proof-path extension when the receipt predates the --known-accumulator snapshot",
73
+ valueHint: "path",
74
+ },
75
+ "consistency-proof": {
76
+ type: "string",
77
+ description:
78
+ "Portable top-up artifact (`forestrie create-consistency-proof`) — tile-free extension of an older receipt into the --known-accumulator snapshot. Untrusted input: it can only fail, never mint trust [FOR-368]",
79
+ valueHint: "path",
80
+ },
81
+ "checkpoint-chain": {
82
+ type: "string",
83
+ description:
84
+ "Retained .sth checkpoint chain — a directory of .sth objects or comma-separated files in chain order. Folds the chain from size 0, authenticating the accumulator at every retained seal from the public log store alone (no tiles, no RPC); the receipt peak may match ANY link [FOR-368]",
85
+ valueHint: "dir|paths",
86
+ },
87
+ },
88
+ run: defineCommandRunner(parseVerifyGrantOptions, runVerifyGrant),
89
+ });
@@ -0,0 +1,92 @@
1
+ import { defineCommandRunner, defineForestrieCommand } from "../commoncli.js";
2
+ import { runVerify } from "../main/verify.js";
3
+ import { parseVerifyOptions } from "../options/verify.js";
4
+
5
+ export default defineForestrieCommand({
6
+ meta: {
7
+ name: "verify",
8
+ description:
9
+ "Verify a receipt offline against the cached checkpoint (ES256; no network) — the standard, SCITT-compatible closer. Give the EXACT registered payload (--payload, e.g. the signed statement) + its --entry-id. Add --univocity/--log-id/--rpc-url to also check the on-chain accumulator [FOR-347]",
10
+ },
11
+ args: {
12
+ genesis: {
13
+ type: "string",
14
+ description:
15
+ "Cached public genesis (genesis.cbor) — genesis-derived offline trust root (or supply --known-log-key instead)",
16
+ valueHint: "path",
17
+ },
18
+ "known-log-key": {
19
+ type: "string",
20
+ description:
21
+ "Caller-known log OWNER key (the delegation issuer), base64 x||y (64 bytes) (env KNOWN_LOG_KEY). Offline signer-provenance anchor that replaces --genesis; asserts (does not prove) the key-to-log binding — --genesis derives it from the grant chain, while the accumulator anchors (--known-accumulator / --rpc-url) supply split-view (freshness is a weaker, separate axis bearing only on coverage). See https://github.com/forestrie/protocol/blob/main/spec/receipt-trust-model.md",
22
+ valueHint: "base64",
23
+ },
24
+ receipt: {
25
+ type: "string",
26
+ description: "COSE receipt file to verify",
27
+ valueHint: "path",
28
+ required: true,
29
+ },
30
+ payload: {
31
+ type: "string",
32
+ description:
33
+ "The EXACT registered payload whose SHA-256 the leaf commits (e.g. the signed statement COSE). A standard COSE Receipt proves leaf = SHA-256(idtimestamp || SHA-256(payload))",
34
+ valueHint: "path",
35
+ required: true,
36
+ },
37
+ "entry-id": {
38
+ type: "string",
39
+ description: "SCRAPI entry id — supplies the leaf idtimestamp",
40
+ valueHint: "id",
41
+ required: true,
42
+ },
43
+ univocity: {
44
+ type: "string",
45
+ description:
46
+ "ImutableUnivocity contract address — enables the chain-anchored check (with --log-id and --rpc-url)",
47
+ valueHint: "address",
48
+ },
49
+ "log-id": {
50
+ type: "string",
51
+ description: "Log id (UUID or hex) for the on-chain accumulator read",
52
+ valueHint: "uuid",
53
+ },
54
+ "rpc-url": {
55
+ type: "string",
56
+ description:
57
+ "JSON-RPC endpoint for the chain-anchored check (default: ${env} → RPC_URL)",
58
+ valueHint: "url",
59
+ },
60
+ "from-block": {
61
+ type: "string",
62
+ description:
63
+ "Lower bound for the buried-peak CheckpointPublished history scan (the forest's deploy block; default earliest) [FOR-368]",
64
+ valueHint: "block",
65
+ },
66
+ "known-accumulator": {
67
+ type: "string",
68
+ description:
69
+ "Cached on-chain accumulator snapshot (CBOR from `forestrie fetch-accumulator`) — the chain-anchored check fully offline, no --rpc-url. Never source it unauthenticated from the log operator's tile store (that re-internalises operator trust). Older receipts extend to a newer snapshot via --massif; newer receipts fail closed",
70
+ valueHint: "path",
71
+ },
72
+ massif: {
73
+ type: "string",
74
+ description:
75
+ "Local massif blob — enables proof-path extension when the receipt predates the --known-accumulator snapshot",
76
+ valueHint: "path",
77
+ },
78
+ "consistency-proof": {
79
+ type: "string",
80
+ description:
81
+ "Portable top-up artifact (`forestrie create-consistency-proof`) — tile-free extension of an older receipt into the --known-accumulator snapshot. Untrusted input: it can only fail, never mint trust [FOR-368]",
82
+ valueHint: "path",
83
+ },
84
+ "checkpoint-chain": {
85
+ type: "string",
86
+ description:
87
+ "Retained .sth checkpoint chain — a directory of .sth objects or comma-separated files in chain order. Folds the chain from size 0, authenticating the accumulator at every retained seal from the public log store alone (no tiles, no RPC); the receipt peak may match ANY link [FOR-368]",
88
+ valueHint: "dir|paths",
89
+ },
90
+ },
91
+ run: defineCommandRunner(parseVerifyOptions, runVerify),
92
+ });
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Tool-wide CLI flags and command wiring for the `forestrie` binary.
3
+ *
4
+ * citty does not pass parent flags into subcommand `run({ args })`, so
5
+ * `commonArgs` is merged into every command via `defineForestrieCommand`
6
+ * (see univocity-tools docs/agents/cli.md — the pattern source).
7
+ */
8
+ import type { ArgsDef, CommandDef } from "citty";
9
+ import { defineAppCommand, verbosityArgs } from "@forestrie/cli-kit";
10
+
11
+ export { defineCommandRunner } from "@forestrie/cli-kit";
12
+
13
+ /** Flags shared by every `forestrie` command. */
14
+ export const commonArgs = {
15
+ ...verbosityArgs,
16
+ json: {
17
+ type: "boolean",
18
+ description: "Machine-readable JSON output on stdout",
19
+ default: false,
20
+ },
21
+ config: {
22
+ type: "string",
23
+ description:
24
+ "Config file path (default: ${env} → FORESTRIE_CONFIG). Stub — config loading lands with the subcommand implementations.",
25
+ valueHint: "path",
26
+ },
27
+ } as const satisfies ArgsDef;
28
+
29
+ /** Wrap `defineCommand` so every node in the tree gets `commonArgs`. */
30
+ export function defineForestrieCommand<T extends ArgsDef>(
31
+ def: CommandDef<T>,
32
+ ): CommandDef<T> {
33
+ return defineAppCommand(commonArgs, def);
34
+ }
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Public library entry: the pure COSE-receipt decoder and renderer that
3
+ * backs `forestrie decode-receipt`.
4
+ *
5
+ * Imported as `@forestrie/forestrie-cli/decode-receipt`. Everything here
6
+ * is runtime-neutral — no `node:*`, no `Bun.*`, no I/O, no network. It
7
+ * takes receipt bytes and returns a display model (plus a text
8
+ * rendering of it), so it runs unchanged in Node, Bun, Deno, a worker
9
+ * or a browser. The only dependencies are `@forestrie/receipt-verify`
10
+ * (the load-bearing receipt parse) and `@forestrie/encoding`.
11
+ *
12
+ * Decoding is display only: it does NOT verify signatures or inclusion.
13
+ * That is `forestrie verify` / `@forestrie/receipt-verify`.
14
+ */
15
+
16
+ export {
17
+ DecodeReceiptError,
18
+ bytesToHex,
19
+ decodeReceipt,
20
+ toJson,
21
+ type DecodeReceiptStage,
22
+ type DecodedClaim,
23
+ type DecodedHeaderEntry,
24
+ type DecodedReceipt,
25
+ type Json,
26
+ } from "./lib/decode-receipt-decode.js";
27
+
28
+ export { renderReceipt } from "./lib/decode-receipt-render.js";
29
+
30
+ export {
31
+ ALG_NAMES,
32
+ COSE_KEY_PARAM_NAMES,
33
+ COSE_SIGN1_TAG,
34
+ CWT_CLAIMS_LABEL,
35
+ CWT_CLAIM_NAMES,
36
+ DELEGATION_CERT_LABEL,
37
+ HEADER_LABELS,
38
+ PROOFS_CONSISTENCY_KEY,
39
+ PROOFS_INCLUSION_KEY,
40
+ PROOF_KIND_NAMES,
41
+ SEAL_PEAK_RECEIPTS_LABEL,
42
+ VDS_LABEL,
43
+ VDS_NAMES,
44
+ VERIFIABLE_PROOFS_LABEL,
45
+ headerLabelInfo,
46
+ type LabelInfo,
47
+ } from "./lib/decode-receipt-labels.js";
48
+
49
+ export {
50
+ CborDecodeError,
51
+ decodeCborMap,
52
+ decodeCborValue,
53
+ isCborTagged,
54
+ type CborTagged,
55
+ type CborValue,
56
+ } from "./lib/decode-receipt-cbor.js";
package/src/index.ts ADDED
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Package entry for `@forestrie/forestrie-cli`.
3
+ *
4
+ * This package is primarily a CLI (`forestrie`). Its one supported
5
+ * library surface is the pure receipt decoder/renderer, re-exported
6
+ * here and also reachable directly as
7
+ * `@forestrie/forestrie-cli/decode-receipt` — prefer the subpath, it is
8
+ * the stable name and will not grow unrelated exports.
9
+ */
10
+ export * from "./decode-receipt.js";
@@ -0,0 +1,7 @@
1
+ /** Constant-time byte-string equality (shared; FOR-418 R6 dedup). */
2
+ export function bytesEqual(a: Uint8Array, b: Uint8Array): boolean {
3
+ if (a.length !== b.length) return false;
4
+ let x = 0;
5
+ for (let i = 0; i < a.length; i++) x |= a[i]! ^ b[i]!;
6
+ return x === 0;
7
+ }