New:Socket for Asana Is Now Available.Learn more
Sign In

@veritasacta/verify

Package Overview
Dependencies
Maintainers
1
Versions
16
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@veritasacta/verify - npm Package Compare versions

Comparing version
0.9.2
to
0.9.3
+4
known-issuers.json
{
"_comment": "Map an Ed25519 verification_key (lowercase hex) to a human label so the CLI prints 'Signer: <label>' instead of raw hex. Add your desk/issuer keys here, or pass your own file with --known-issuers <path>. This is a display aid layered on --key pinning, never a trust shortcut: an unlabeled key still verifies, and a label is only as good as the map you chose to load.",
"_example": "0000000000000000000000000000000000000000000000000000000000000000 -> Example Desk (remove this)"
}
{
"type": "scopeblind.legate.proof-pack.v1",
"generated_at": "2026-06-22T23:31:19.884Z",
"period": null,
"position_blind": true,
"runtime": {
"name": "Toms-MacBook-Pro.local",
"verification_key": "ecfc8fe8e791d84204e4889c2ccae46da41d90c8bb88f028bee1f96790c3ae2a"
},
"mandate": {
"name": "Global Macro IMA",
"sha256": "5ac8a3803737c74cbb5221ed0983ac8c1cc28954b42ed75e372ef275fd918df2",
"mode": "enforce",
"rule_count": 9,
"coverage": {
"local": [
"gross-exposure",
"net-exposure",
"soft-gross-band",
"class-gross-rates",
"class-gross-fx",
"class-gross-equity",
"class-gross-credit",
"class-gross-commodity",
"dv01-book"
],
"order_context": [],
"delegated": []
}
},
"policy": {
"name": "Legate default agent mandate",
"sha256": "650d036c3b05675f3719168a41bf0266482728b5f0156c646b2649cd804c040d",
"version": "1",
"rule_count": 5
},
"book": null,
"governed_actions": {
"evaluated": 0,
"allowed": 0,
"held": 0,
"blocked": 0,
"would_block": 0
},
"restraint": {
"blocked": 0,
"held": 0,
"by_rule": []
},
"shadow": {
"observed": 2,
"would_block": 0,
"would_hold": 2,
"by_rule": [
{
"rule": "gross-exposure",
"count": 2
},
{
"rule": "net-exposure",
"count": 2
},
{
"rule": "class-gross-rates",
"count": 2
},
{
"rule": "class-gross-fx",
"count": 2
},
{
"rule": "class-gross-equity",
"count": 2
},
{
"rule": "class-gross-credit",
"count": 2
},
{
"rule": "class-gross-commodity",
"count": 2
}
],
"first_at": "2026-06-22T23:31:19.814Z",
"last_at": "2026-06-22T23:31:19.849Z"
},
"session_merkle_root": "66308d59fa859823fe9ff774f4f4e91cb025f391327858c0e4192ab84504346d",
"receipt_count": 1,
"signer_kid": "sb:legate:ecfc8fe8",
"verification_key": "ecfc8fe8e791d84204e4889c2ccae46da41d90c8bb88f028bee1f96790c3ae2a",
"sha256": "b6c421a1d86cbfe34f9748b3976f2a8a3d3cd64cb6467f07c85e58f43ab7c360",
"signature": "31f1b2090f74157a55445411c1555141f656a88f089a459488e88e155f37d5a633fa62786d4974699e19536221328882651e6d8f471cc1226450f5d203e8eb0b"
}
{
"payload": {
"schema": "scopeblind.macro.alert/1",
"engine_version": "macro-engine/0.1.0",
"as_of": "2025-08-23",
"alert_id": "915720cc951de3dfb99437ebac0362f02947160eca28841e6803c37979019cbb",
"kind": "market_state_change",
"severity": "critical",
"title": "Market state: mixed -> stress",
"detail": "Daily market-state classification changed (confidence 0.8).",
"refs": [
{
"schema": "scopeblind.macro.market-state/1",
"as_of": "2025-08-23",
"digest": "d9602f7915b69bcbf7f86c0cf1b0387965e1b448918be92339ed96d138449d80"
},
{
"schema": "scopeblind.macro.market-state/1",
"as_of": "2025-02-05",
"digest": "d47770c9fdcbe921596497fc1f63d18f86d8bbef302abc060d4d0e1cb7dc9e53"
}
],
"budget": {
"position": 1,
"max_per_day": 2
}
},
"digest": "bb942d2f4fe547ffba9e7eec6518d32d5d61019c6c85da6aad4dfa051b3df460",
"signature": "a3ddc18d8087ae63a4b4d967d3d12a28db2476ef143f0ed21d2d1b4ecae7187eb8310a2e87ee5534c2250a533deeadb450c6e1003bcf1c43b731f96929738800",
"verification_key": "e324c4149db27151f65df25d528d3037d3b3bc4165b0d28c0769369cba958ae3"
}
{
"payload": {
"schema": "scopeblind.macro.journal-entry/1",
"engine_version": "macro-engine/0.1.0",
"as_of": "2025-08-23",
"author": "demo-model",
"note": "Regime read stagflation while the daily tape printed stress. Cut gross and lengthened nothing; the book is long the wrong factors here.",
"references": [
{
"schema": "scopeblind.macro.market-state/1",
"as_of": "2025-08-23",
"digest": "f469ddc93ce803456bf6eed265c1ffa94690bb3ed972e9dff95c7dab52972e94"
},
{
"schema": "scopeblind.macro.vulnerability/1",
"as_of": "2025-08-23",
"digest": "d277793511a0dcda199889d8beedbe849146cf0fc4cb216ce1dc77cadf20b237"
},
{
"schema": "scopeblind.macro.regime-snapshot/1",
"as_of": "2026-05-01",
"digest": "27a4b9dd293ae77487e919adbf428e4911da62907c39dd017c50376ad9e77591"
}
],
"tags": [
"risk-off",
"stagflation",
"vulnerability"
]
},
"digest": "95415964066eaf10e5de3e49dd18763c8c7d79099baa0bbe670b402f52243923",
"signature": "adce443ba5de6d2e2edea9b5cc19744ae0a7842ad552860c03e895e5393434f4f0448bb5eb5d81f2aae7cbf222494931bfcab30ad465931f073ca2350e042b0c",
"verification_key": "e324c4149db27151f65df25d528d3037d3b3bc4165b0d28c0769369cba958ae3"
}
{
"payload": {
"schema": "scopeblind.macro.market-state/1",
"engine_version": "macro-engine/0.1.0",
"as_of": "2025-08-23",
"universe_digest": "e71b066c5c05624984187e810d8dc3422964825d7cefa5338f738d57a1e1dd76",
"inputs_digest": "51b8add91569d3da3b761f5c0a1fefba25fabbe486214fe36a6204347cc904e3",
"pillars": {
"trend": -2,
"breadth": 0,
"liquidity": -2,
"credit": -2,
"volatility": -2
},
"evidence": {
"trend": {
"inputs": [
{
"symbol": "SPY",
"feature": "ma_structure",
"value": -2,
"vote": -2
}
],
"missing": [
"QQQ",
"ACWI"
]
},
"breadth": {
"inputs": [
{
"symbol": "RSP/SPY",
"feature": "ret20d_z",
"value": 0,
"vote": 0
},
{
"symbol": "IWM/SPY",
"feature": "ret20d_z",
"value": 0,
"vote": 0
}
],
"missing": []
},
"liquidity": {
"inputs": [
{
"symbol": "UUP",
"feature": "ret20d_z_inv",
"value": -6.554929,
"vote": -2
},
{
"symbol": "BTCUSD",
"feature": "ret20d_z",
"value": -6.478535,
"vote": -2
}
],
"missing": [
"EEM/EFA",
"SMH/SPY"
]
},
"credit": {
"inputs": [
{
"symbol": "HYG/IEF",
"feature": "ret20d_z",
"value": -6.352958,
"vote": -2
}
],
"missing": [
"LQD/IEF",
"XLF/SPY"
]
},
"volatility": {
"inputs": [
{
"symbol": "SPY",
"feature": "rvol20_pctile_1y",
"value": 0.932806,
"vote": -2
}
],
"missing": [
"VIX"
]
}
},
"classification": "stress",
"confidence": 0.8,
"would_change": [
"robust: no single-pillar one-notch change alters this classification"
],
"notes": [
"HYG: HYG/IEF ratio proxies HY OAS direction intraday; true OAS (daily, lagged) comes from FRED BAMLH0A0HYM2 in the regime layer.",
"RSP: Equal-weight ratio proxies constituent breadth; true %>200dma needs constituent data (licensing-gated).",
"UUP: DXY proxy; futures DX licensing-gated at this tier.",
"degraded: missing inputs ACWI, EEM/EFA, LQD/IEF, QQQ, SMH/SPY, VIX, XLF/SPY"
]
},
"digest": "f469ddc93ce803456bf6eed265c1ffa94690bb3ed972e9dff95c7dab52972e94",
"signature": "0f93202e78e81ea84ba36e2c2e787ef493aba32c61140a948553f314a3403f042220ac64cf04e8d22e9044b2e6e9712587b1e023cb0dd796353543609aec380a",
"verification_key": "e324c4149db27151f65df25d528d3037d3b3bc4165b0d28c0769369cba958ae3"
}
{
"payload": {
"schema": "scopeblind.macro.price-snapshot/1",
"engine_version": "macro-engine/0.1.0",
"as_of": "2026-06-12T20:00:00Z",
"source": "Massive Market Data daily settle (delayed feed; not a live tick)",
"delay_minutes": 15,
"levels": {
"rates": {
"level": 85.77,
"instrument": "TLT",
"unit": "price",
"note": "long-duration UST proxy; loads via DV01, not notional"
},
"equity": {
"level": 741.75,
"instrument": "SPY",
"unit": "price",
"multiplier": 500,
"note": "ES notional = level x 500 (x10 index ratio, $50 point value)"
},
"fx_eur": {
"level": 1.15655,
"instrument": "EURUSD",
"unit": "fx_rate"
},
"fx_jpy": {
"level": 160.215,
"instrument": "USDJPY",
"unit": "fx_rate"
},
"credit_ig": {
"level": 109.01,
"instrument": "LQD",
"unit": "price",
"note": "IG proxy; loads via CS01, not notional"
},
"credit_hy": {
"level": 79.94,
"instrument": "HYG",
"unit": "price",
"note": "HY proxy; loads via CS01, not notional"
},
"commodity_oil": {
"level": 125.43,
"instrument": "USO",
"unit": "price",
"note": "crude proxy ETF (roll-affected); provenance only"
},
"commodity_gold": {
"level": 386.54,
"instrument": "GLD",
"unit": "price",
"note": "gold proxy ETF; provenance only"
}
},
"coverage": [
"commodity_gold",
"commodity_oil",
"credit_hy",
"credit_ig",
"equity",
"fx_eur",
"fx_jpy",
"rates"
],
"missing": [],
"notes": [
"levels are official daily closes (settle) for the 2026-06-12 session, from a delayed feed",
"instruments are liquid ETF/FX proxies, not the futures themselves; the snapshot never overstates what it observed",
"only the equity (ES) factor carries a notional multiplier; the rest are signed provenance and load via DV01/CS01"
]
},
"digest": "32a46e47fd2639b9991dfd8133c600c8ed7e9a86b56f3ec5372870c35624c165",
"signature": "676678d1d4ce516869d80f185bf3fd207d33c02109e4deb4e6fc5a8a2a557ed3ac6c12b3f8f12d55c03b7670a20e457dd86ccfbd5fe994015d0ed2e8f782a50b",
"verification_key": "e324c4149db27151f65df25d528d3037d3b3bc4165b0d28c0769369cba958ae3"
}
{
"payload": {
"schema": "scopeblind.macro.regime-snapshot/1",
"engine_version": "macro-engine/0.1.0",
"as_of": "2026-05-01",
"pillars": {
"growth": -2,
"inflation": 2,
"liquidity": -2,
"policy_freedom": -2,
"credit_conditions": -2
},
"inputs": [
{
"series_id": "ICSA",
"transform": "diff13w",
"value": 35123.671753,
"z": -6.764746,
"vote": -2,
"asof_digest": "73fa36d5ba21ff19e82757760ffc56899c4d33ca617cbdf79523e2eb1550f573",
"latest_vintage": "2026-04-29"
},
{
"series_id": "PAYEMS",
"transform": "mom3_ann",
"value": -0.036344,
"z": -3.501479,
"vote": -2,
"asof_digest": "64ca109e3b7d52348a813e5c7fa3695ce0801b30a9ac8cc2aa7cc248e6292abf",
"latest_vintage": "2026-04-08"
},
{
"series_id": "INDPRO",
"transform": "mom6_ann",
"value": -0.036233,
"z": -4.775509,
"vote": -2,
"asof_digest": "880c1c9898d45bca6a5d9803d3a687e7702ada5b4dee082d68e685fb8540be82",
"latest_vintage": "2026-04-17"
},
{
"series_id": "RSXFS",
"transform": "mom3_ann",
"value": -0.036344,
"z": -3.485408,
"vote": -2,
"asof_digest": "87bb798c4e9efdfb41f31a11cc3f49f96fe9db48d753cd5aaa0643f3b4a59e1d",
"latest_vintage": "2026-04-17"
},
{
"series_id": "USALOLITONOSTSAM",
"transform": "diff6m",
"value": -1.152544,
"z": -5.744365,
"vote": -2,
"asof_digest": "4e7ae6048b479286b801201eebf6db1d28ada976b1841d8b41cb5d95c99d9929",
"latest_vintage": "2026-04-10"
},
{
"series_id": "CPILFESL",
"transform": "mom3_ann",
"value": 0.069551,
"z": 3.342129,
"vote": 2,
"asof_digest": "b0a91055ce6a6a879010796266ef9236bb911a888a54ce6af7b24e6010183ca3",
"latest_vintage": "2026-04-14"
},
{
"series_id": "PCEPILFE",
"transform": "mom3_ann",
"value": 0.067001,
"z": 3.342148,
"vote": 2,
"asof_digest": "b53a27bb365e01fa1e2ac25f446930ff6f852c4ed2a6fd2eefff38cc96c9da57",
"latest_vintage": "2026-04-29"
},
{
"series_id": "T10YIE",
"transform": "diff3m",
"value": 0.153311,
"z": 5.226471,
"vote": 2,
"asof_digest": "b839addb59d3c4a84a0a4b27e6ad47636b83a3729b1cc7144bea8dd58db2ff73",
"latest_vintage": "2026-05-01"
},
{
"series_id": "DCOILWTICO",
"transform": "mom3_ann",
"value": 0.653636,
"z": 5.382054,
"vote": 2,
"asof_digest": "97178dd3c33fa82c7479b66c6132a7d8d96e47ccc39ffc4ba93d64cc38ab65b8",
"latest_vintage": "2026-05-01"
},
{
"series_id": "AHETPI",
"transform": "mom3_ann",
"value": 0.067001,
"z": 3.3094,
"vote": 2,
"asof_digest": "783bab21a0e6c7c761d4c62ceab7c582cefa6d050b2e03898a4a62f80971ef90",
"latest_vintage": "2026-04-08"
},
{
"series_id": "WALCL",
"transform": "diff13w",
"value": -355139.244176,
"z": -6.539508,
"vote": -2,
"asof_digest": "af2dd3799a152fdb8171b203aec25bd0b0e276e87df7be9bdc8a989f48a51346",
"latest_vintage": "2026-04-25"
},
{
"series_id": "WTREGEN",
"transform": "diff13w",
"value": 98346.28091,
"z": -6.764746,
"vote": -2,
"asof_digest": "0e493e335271dcbeeae69f95d4683b35988eba5248e525fed6151b840f127989",
"latest_vintage": "2026-04-25"
},
{
"series_id": "RRPONTSYD",
"transform": "diff13w",
"value": 158.625566,
"z": -5.60151,
"vote": -2,
"asof_digest": "62bd49d946bd279358ff87d32d370fa6d0a68c37682b1ba7ad99e3bfd1687daa",
"latest_vintage": "2026-05-01"
},
{
"series_id": "M2SL",
"transform": "mom6_ann",
"value": -0.036233,
"z": -4.775509,
"vote": -2,
"asof_digest": "8b96e538db1b6659919cb95408ff3d5ee407783a03e7f26e0920aa50123e9a19",
"latest_vintage": "2026-04-27"
},
{
"series_id": "DTWEXBGS",
"transform": "diff3m",
"value": 7.998853,
"z": -5.226471,
"vote": -2,
"asof_digest": "05d20fa0c9d7d5f2dff3d84ec7ff62579e7eaea87ff66bb50a2a8e869165de5d",
"latest_vintage": "2026-05-01"
},
{
"series_id": "DFEDTARU",
"transform": "level",
"value": 0.999608,
"z": null,
"vote": null,
"asof_digest": "3922373305be0976cddffb6778d61343e9289d3f6d3fe8039a2ca95a765c735f",
"latest_vintage": "2026-05-01"
},
{
"series_id": "DFII10",
"transform": "diff3m",
"value": 0.119983,
"z": -5.226471,
"vote": -2,
"asof_digest": "474a4dd5f297eb398235b01334b7fc283979b30c96c1b1ac57351eedc6064cdf",
"latest_vintage": "2026-05-01"
},
{
"series_id": "T5YIFR",
"transform": "level",
"value": 3.201024,
"z": null,
"vote": -2,
"asof_digest": "b8e076fbcd90990be22e3f6fc53461a74d5f0a4553cb0152b70c4fea50f4530f",
"latest_vintage": "2026-05-01"
},
{
"series_id": "BAMLH0A0HYM2",
"transform": "diff13w",
"value": 1.110379,
"z": -5.60151,
"vote": -2,
"asof_digest": "8ec3d58658b36d414849b002fef15350817a81ddcb81e9e203a9ada8bd8d1c3f",
"latest_vintage": "2026-05-01"
},
{
"series_id": "BAMLC0A0CM",
"transform": "diff13w",
"value": 0.073323,
"z": -5.226471,
"vote": -2,
"asof_digest": "370a4e107534d46a1a542d1e16ce9f9f4a17aeeb377f9e5c4481f1e0f3a2facb",
"latest_vintage": "2026-05-01"
},
{
"series_id": "NFCI",
"transform": "level",
"value": 0.550016,
"z": null,
"vote": -2,
"asof_digest": "f0f61455659b69270627f8c5cf767fc2f5dc72985c36d682edad857629df4d9d",
"latest_vintage": "2026-04-29"
},
{
"series_id": "NET_LIQUIDITY",
"transform": "diff13w",
"value": -650.297517,
"z": -6.328823,
"vote": -2,
"asof_digest": "1e43b543c63afcf7659de4c5ddaf99ba96dc4d1c7f55052aa392b0aadd1207a9",
"latest_vintage": "2026-04-25"
},
{
"series_id": "REAL_POLICY_RATE",
"transform": "level",
"value": -3.905295,
"z": null,
"vote": -2,
"asof_digest": "9427fbf69d076b6f3a9536742e8d4f2ac15c4e4085075a8b60273d34970b0f4d",
"latest_vintage": "2026-05-01"
}
],
"vintage_digest": "77304f7e1203df3211824c78c7c9e800a0dd52b744f5173324524174ad96d3bc",
"candidate_regime": "stagflation",
"regime": "stagflation",
"liquidity_overlay": "contraction",
"hysteresis": {
"current": "stagflation",
"candidate": null,
"candidate_weeks": 0,
"weeks_since_switch": 999
},
"transition": null,
"playbook": {
"prefer": [
"energy",
"gold",
"dollar",
"defensives",
"cash"
],
"avoid": [
"unhedged cyclicals",
"levered credit"
],
"confidence": "medium"
},
"confidence": 0.956522,
"would_change": [
"robust: no single-pillar one-notch change alters this candidate regime"
],
"notes": [
"degraded: no usable vote from DFEDTARU",
"Net liquidity (WALCL - TGA - RRP) validity is regime-dependent: strongest when reserve scarcity binds.",
"PMI family is licensing-gated: growth diffusion uses claims, payrolls, production, retail, and OECD CLI."
]
},
"digest": "27a4b9dd293ae77487e919adbf428e4911da62907c39dd017c50376ad9e77591",
"signature": "806c531043618f2c4da47180ace2020def35fbf12bbf603061e4fb3264b97940c2bcfd50e395d16c8f2e45bdbe2ff69a84c00ddbe330fcaa29bc95296da66207",
"verification_key": "e324c4149db27151f65df25d528d3037d3b3bc4165b0d28c0769369cba958ae3"
}
{
"payload": {
"schema": "scopeblind.macro.tape-snapshot/1",
"engine_version": "macro-engine/0.1.0",
"as_of": "2025-08-23",
"session": "daily_close",
"tape_type": "mixed",
"coherence": 0,
"material": true,
"signals": [
{
"id": "breadth_rel",
"z": 0
},
{
"id": "credit",
"z": -2.631816
},
{
"id": "dollar",
"z": 3.61392
},
{
"id": "duration",
"z": 3.20995
},
{
"id": "equity",
"z": -3.860863
},
{
"id": "high_beta",
"z": -4.467346
},
{
"id": "smallcap_rel",
"z": 0
}
],
"unavailable": [
"banks_rel",
"copper",
"gold",
"growth_beta",
"oil"
],
"untestable_types": [
"inflation_shock"
],
"attribution": {
"tier": "unknown",
"detail": "material moves without a coherent cross-asset pattern or scheduled catalyst",
"events": []
},
"inputs_digest": "c202156a133cdee47311f843fbc18082311ca653dd4293496ea1c47346fa68c7",
"would_change": [
"a coherent cross-asset pattern forming would move this off mixed"
],
"notes": [
"degraded: unavailable signals banks_rel, copper, gold, growth_beta, oil",
"untestable tape types with current data: inflation_shock",
"session basis: daily close-to-close; intraday windows plug into the same rules when a live feed is configured"
]
},
"digest": "43e98d770cb3b4e47c915164d7fe0aa7ec257968978a5cd1aa914e9e2403decd",
"signature": "f7cf06b796186a7a6b76053f30b5dd3b96affb6b3853df78550719576d0059bc4a36d34c74afd3d122770e34cbdda03e3f0adcd794c314396a411d3ee5f2590f",
"verification_key": "e324c4149db27151f65df25d528d3037d3b3bc4165b0d28c0769369cba958ae3"
}
{
"schema": "scopeblind.macro.track-record-bundle/1",
"version": "0.1.0",
"exported_at": "2026-05-01T00:00:00Z",
"model_verification_key": "e324c4149db27151f65df25d528d3037d3b3bc4165b0d28c0769369cba958ae3",
"custody": "dev-deterministic",
"period": {
"from": "2025-01-02",
"to": "2026-05-01"
},
"snapshots": [
{
"payload": {
"schema": "scopeblind.macro.market-state/1",
"engine_version": "macro-engine/0.1.0",
"as_of": "2025-08-23",
"universe_digest": "e71b066c5c05624984187e810d8dc3422964825d7cefa5338f738d57a1e1dd76",
"inputs_digest": "51b8add91569d3da3b761f5c0a1fefba25fabbe486214fe36a6204347cc904e3",
"pillars": {
"trend": -2,
"breadth": 0,
"liquidity": -2,
"credit": -2,
"volatility": -2
},
"evidence": {
"trend": {
"inputs": [
{
"symbol": "SPY",
"feature": "ma_structure",
"value": -2,
"vote": -2
}
],
"missing": [
"QQQ",
"ACWI"
]
},
"breadth": {
"inputs": [
{
"symbol": "RSP/SPY",
"feature": "ret20d_z",
"value": 0,
"vote": 0
},
{
"symbol": "IWM/SPY",
"feature": "ret20d_z",
"value": 0,
"vote": 0
}
],
"missing": []
},
"liquidity": {
"inputs": [
{
"symbol": "UUP",
"feature": "ret20d_z_inv",
"value": -6.554929,
"vote": -2
},
{
"symbol": "BTCUSD",
"feature": "ret20d_z",
"value": -6.478535,
"vote": -2
}
],
"missing": [
"EEM/EFA",
"SMH/SPY"
]
},
"credit": {
"inputs": [
{
"symbol": "HYG/IEF",
"feature": "ret20d_z",
"value": -6.352958,
"vote": -2
}
],
"missing": [
"LQD/IEF",
"XLF/SPY"
]
},
"volatility": {
"inputs": [
{
"symbol": "SPY",
"feature": "rvol20_pctile_1y",
"value": 0.932806,
"vote": -2
}
],
"missing": [
"VIX"
]
}
},
"classification": "stress",
"confidence": 0.8,
"would_change": [
"robust: no single-pillar one-notch change alters this classification"
],
"notes": [
"HYG: HYG/IEF ratio proxies HY OAS direction intraday; true OAS (daily, lagged) comes from FRED BAMLH0A0HYM2 in the regime layer.",
"RSP: Equal-weight ratio proxies constituent breadth; true %>200dma needs constituent data (licensing-gated).",
"UUP: DXY proxy; futures DX licensing-gated at this tier.",
"degraded: missing inputs ACWI, EEM/EFA, LQD/IEF, QQQ, SMH/SPY, VIX, XLF/SPY"
]
},
"digest": "f469ddc93ce803456bf6eed265c1ffa94690bb3ed972e9dff95c7dab52972e94",
"signature": "0f93202e78e81ea84ba36e2c2e787ef493aba32c61140a948553f314a3403f042220ac64cf04e8d22e9044b2e6e9712587b1e023cb0dd796353543609aec380a",
"verification_key": "e324c4149db27151f65df25d528d3037d3b3bc4165b0d28c0769369cba958ae3"
},
{
"payload": {
"schema": "scopeblind.macro.tape-snapshot/1",
"engine_version": "macro-engine/0.1.0",
"as_of": "2025-08-23",
"session": "daily_close",
"tape_type": "mixed",
"coherence": 0,
"material": true,
"signals": [
{
"id": "breadth_rel",
"z": 0
},
{
"id": "credit",
"z": -2.631816
},
{
"id": "dollar",
"z": 3.61392
},
{
"id": "duration",
"z": 3.20995
},
{
"id": "equity",
"z": -3.860863
},
{
"id": "high_beta",
"z": -4.467346
},
{
"id": "smallcap_rel",
"z": 0
}
],
"unavailable": [
"banks_rel",
"copper",
"gold",
"growth_beta",
"oil"
],
"untestable_types": [
"inflation_shock"
],
"attribution": {
"tier": "unknown",
"detail": "material moves without a coherent cross-asset pattern or scheduled catalyst",
"events": []
},
"inputs_digest": "c202156a133cdee47311f843fbc18082311ca653dd4293496ea1c47346fa68c7",
"would_change": [
"a coherent cross-asset pattern forming would move this off mixed"
],
"notes": [
"degraded: unavailable signals banks_rel, copper, gold, growth_beta, oil",
"untestable tape types with current data: inflation_shock",
"session basis: daily close-to-close; intraday windows plug into the same rules when a live feed is configured"
]
},
"digest": "43e98d770cb3b4e47c915164d7fe0aa7ec257968978a5cd1aa914e9e2403decd",
"signature": "f7cf06b796186a7a6b76053f30b5dd3b96affb6b3853df78550719576d0059bc4a36d34c74afd3d122770e34cbdda03e3f0adcd794c314396a411d3ee5f2590f",
"verification_key": "e324c4149db27151f65df25d528d3037d3b3bc4165b0d28c0769369cba958ae3"
},
{
"payload": {
"schema": "scopeblind.macro.regime-snapshot/1",
"engine_version": "macro-engine/0.1.0",
"as_of": "2026-05-01",
"pillars": {
"growth": -2,
"inflation": 2,
"liquidity": -2,
"policy_freedom": -2,
"credit_conditions": -2
},
"inputs": [
{
"series_id": "ICSA",
"transform": "diff13w",
"value": 35123.671753,
"z": -6.764746,
"vote": -2,
"asof_digest": "73fa36d5ba21ff19e82757760ffc56899c4d33ca617cbdf79523e2eb1550f573",
"latest_vintage": "2026-04-29"
},
{
"series_id": "PAYEMS",
"transform": "mom3_ann",
"value": -0.036344,
"z": -3.501479,
"vote": -2,
"asof_digest": "64ca109e3b7d52348a813e5c7fa3695ce0801b30a9ac8cc2aa7cc248e6292abf",
"latest_vintage": "2026-04-08"
},
{
"series_id": "INDPRO",
"transform": "mom6_ann",
"value": -0.036233,
"z": -4.775509,
"vote": -2,
"asof_digest": "880c1c9898d45bca6a5d9803d3a687e7702ada5b4dee082d68e685fb8540be82",
"latest_vintage": "2026-04-17"
},
{
"series_id": "RSXFS",
"transform": "mom3_ann",
"value": -0.036344,
"z": -3.485408,
"vote": -2,
"asof_digest": "87bb798c4e9efdfb41f31a11cc3f49f96fe9db48d753cd5aaa0643f3b4a59e1d",
"latest_vintage": "2026-04-17"
},
{
"series_id": "USALOLITONOSTSAM",
"transform": "diff6m",
"value": -1.152544,
"z": -5.744365,
"vote": -2,
"asof_digest": "4e7ae6048b479286b801201eebf6db1d28ada976b1841d8b41cb5d95c99d9929",
"latest_vintage": "2026-04-10"
},
{
"series_id": "CPILFESL",
"transform": "mom3_ann",
"value": 0.069551,
"z": 3.342129,
"vote": 2,
"asof_digest": "b0a91055ce6a6a879010796266ef9236bb911a888a54ce6af7b24e6010183ca3",
"latest_vintage": "2026-04-14"
},
{
"series_id": "PCEPILFE",
"transform": "mom3_ann",
"value": 0.067001,
"z": 3.342148,
"vote": 2,
"asof_digest": "b53a27bb365e01fa1e2ac25f446930ff6f852c4ed2a6fd2eefff38cc96c9da57",
"latest_vintage": "2026-04-29"
},
{
"series_id": "T10YIE",
"transform": "diff3m",
"value": 0.153311,
"z": 5.226471,
"vote": 2,
"asof_digest": "b839addb59d3c4a84a0a4b27e6ad47636b83a3729b1cc7144bea8dd58db2ff73",
"latest_vintage": "2026-05-01"
},
{
"series_id": "DCOILWTICO",
"transform": "mom3_ann",
"value": 0.653636,
"z": 5.382054,
"vote": 2,
"asof_digest": "97178dd3c33fa82c7479b66c6132a7d8d96e47ccc39ffc4ba93d64cc38ab65b8",
"latest_vintage": "2026-05-01"
},
{
"series_id": "AHETPI",
"transform": "mom3_ann",
"value": 0.067001,
"z": 3.3094,
"vote": 2,
"asof_digest": "783bab21a0e6c7c761d4c62ceab7c582cefa6d050b2e03898a4a62f80971ef90",
"latest_vintage": "2026-04-08"
},
{
"series_id": "WALCL",
"transform": "diff13w",
"value": -355139.244176,
"z": -6.539508,
"vote": -2,
"asof_digest": "af2dd3799a152fdb8171b203aec25bd0b0e276e87df7be9bdc8a989f48a51346",
"latest_vintage": "2026-04-25"
},
{
"series_id": "WTREGEN",
"transform": "diff13w",
"value": 98346.28091,
"z": -6.764746,
"vote": -2,
"asof_digest": "0e493e335271dcbeeae69f95d4683b35988eba5248e525fed6151b840f127989",
"latest_vintage": "2026-04-25"
},
{
"series_id": "RRPONTSYD",
"transform": "diff13w",
"value": 158.625566,
"z": -5.60151,
"vote": -2,
"asof_digest": "62bd49d946bd279358ff87d32d370fa6d0a68c37682b1ba7ad99e3bfd1687daa",
"latest_vintage": "2026-05-01"
},
{
"series_id": "M2SL",
"transform": "mom6_ann",
"value": -0.036233,
"z": -4.775509,
"vote": -2,
"asof_digest": "8b96e538db1b6659919cb95408ff3d5ee407783a03e7f26e0920aa50123e9a19",
"latest_vintage": "2026-04-27"
},
{
"series_id": "DTWEXBGS",
"transform": "diff3m",
"value": 7.998853,
"z": -5.226471,
"vote": -2,
"asof_digest": "05d20fa0c9d7d5f2dff3d84ec7ff62579e7eaea87ff66bb50a2a8e869165de5d",
"latest_vintage": "2026-05-01"
},
{
"series_id": "DFEDTARU",
"transform": "level",
"value": 0.999608,
"z": null,
"vote": null,
"asof_digest": "3922373305be0976cddffb6778d61343e9289d3f6d3fe8039a2ca95a765c735f",
"latest_vintage": "2026-05-01"
},
{
"series_id": "DFII10",
"transform": "diff3m",
"value": 0.119983,
"z": -5.226471,
"vote": -2,
"asof_digest": "474a4dd5f297eb398235b01334b7fc283979b30c96c1b1ac57351eedc6064cdf",
"latest_vintage": "2026-05-01"
},
{
"series_id": "T5YIFR",
"transform": "level",
"value": 3.201024,
"z": null,
"vote": -2,
"asof_digest": "b8e076fbcd90990be22e3f6fc53461a74d5f0a4553cb0152b70c4fea50f4530f",
"latest_vintage": "2026-05-01"
},
{
"series_id": "BAMLH0A0HYM2",
"transform": "diff13w",
"value": 1.110379,
"z": -5.60151,
"vote": -2,
"asof_digest": "8ec3d58658b36d414849b002fef15350817a81ddcb81e9e203a9ada8bd8d1c3f",
"latest_vintage": "2026-05-01"
},
{
"series_id": "BAMLC0A0CM",
"transform": "diff13w",
"value": 0.073323,
"z": -5.226471,
"vote": -2,
"asof_digest": "370a4e107534d46a1a542d1e16ce9f9f4a17aeeb377f9e5c4481f1e0f3a2facb",
"latest_vintage": "2026-05-01"
},
{
"series_id": "NFCI",
"transform": "level",
"value": 0.550016,
"z": null,
"vote": -2,
"asof_digest": "f0f61455659b69270627f8c5cf767fc2f5dc72985c36d682edad857629df4d9d",
"latest_vintage": "2026-04-29"
},
{
"series_id": "NET_LIQUIDITY",
"transform": "diff13w",
"value": -650.297517,
"z": -6.328823,
"vote": -2,
"asof_digest": "1e43b543c63afcf7659de4c5ddaf99ba96dc4d1c7f55052aa392b0aadd1207a9",
"latest_vintage": "2026-04-25"
},
{
"series_id": "REAL_POLICY_RATE",
"transform": "level",
"value": -3.905295,
"z": null,
"vote": -2,
"asof_digest": "9427fbf69d076b6f3a9536742e8d4f2ac15c4e4085075a8b60273d34970b0f4d",
"latest_vintage": "2026-05-01"
}
],
"vintage_digest": "77304f7e1203df3211824c78c7c9e800a0dd52b744f5173324524174ad96d3bc",
"candidate_regime": "stagflation",
"regime": "stagflation",
"liquidity_overlay": "contraction",
"hysteresis": {
"current": "stagflation",
"candidate": null,
"candidate_weeks": 0,
"weeks_since_switch": 999
},
"transition": null,
"playbook": {
"prefer": [
"energy",
"gold",
"dollar",
"defensives",
"cash"
],
"avoid": [
"unhedged cyclicals",
"levered credit"
],
"confidence": "medium"
},
"confidence": 0.956522,
"would_change": [
"robust: no single-pillar one-notch change alters this candidate regime"
],
"notes": [
"degraded: no usable vote from DFEDTARU",
"Net liquidity (WALCL - TGA - RRP) validity is regime-dependent: strongest when reserve scarcity binds.",
"PMI family is licensing-gated: growth diffusion uses claims, payrolls, production, retail, and OECD CLI."
]
},
"digest": "27a4b9dd293ae77487e919adbf428e4911da62907c39dd017c50376ad9e77591",
"signature": "806c531043618f2c4da47180ace2020def35fbf12bbf603061e4fb3264b97940c2bcfd50e395d16c8f2e45bdbe2ff69a84c00ddbe330fcaa29bc95296da66207",
"verification_key": "e324c4149db27151f65df25d528d3037d3b3bc4165b0d28c0769369cba958ae3"
},
{
"payload": {
"schema": "scopeblind.macro.vulnerability/1",
"engine_version": "macro-engine/0.1.0",
"as_of": "2025-08-23",
"posture": {
"regime": "stagflation",
"market_state": "stress",
"refs": [
{
"schema": "scopeblind.macro.market-state/1",
"as_of": "2025-08-23",
"digest": "f469ddc93ce803456bf6eed265c1ffa94690bb3ed972e9dff95c7dab52972e94"
},
{
"schema": "scopeblind.macro.tape-snapshot/1",
"as_of": "2025-08-23",
"digest": "43e98d770cb3b4e47c915164d7fe0aa7ec257968978a5cd1aa914e9e2403decd"
},
{
"schema": "scopeblind.macro.regime-snapshot/1",
"as_of": "2026-05-01",
"digest": "27a4b9dd293ae77487e919adbf428e4911da62907c39dd017c50376ad9e77591"
}
]
},
"factor_exposures": [
{
"factor": "equity_beta",
"net": 0.55,
"gross": 0.55,
"contributors": [
{
"symbol": "SPY",
"weight": 0.45
},
{
"symbol": "EEM",
"weight": 0.1
}
]
},
{
"factor": "duration",
"net": 0.3,
"gross": 0.3,
"contributors": [
{
"symbol": "IEF",
"weight": 0.3
}
]
},
{
"factor": "credit",
"net": 0.15,
"gross": 0.15,
"contributors": [
{
"symbol": "HYG",
"weight": 0.15
}
]
},
{
"factor": "usd_sensitivity",
"net": 0.1,
"gross": 0.1,
"contributors": [
{
"symbol": "EEM",
"weight": 0.1
}
]
},
{
"factor": "global",
"net": 0.1,
"gross": 0.1,
"contributors": [
{
"symbol": "EEM",
"weight": 0.1
}
]
}
],
"betas": [
{
"factor": "equity_beta",
"proxy": "SPY",
"beta": 0.562937,
"r2": 0.926912,
"n": 120
},
{
"factor": "duration",
"proxy": "IEF",
"beta": -1.916486,
"r2": 0.368425,
"n": 120
},
{
"factor": "credit",
"proxy": "HYG",
"beta": 0.344651,
"r2": 0.727716,
"n": 120
},
{
"factor": "usd",
"proxy": "UUP",
"beta": -1.562837,
"r2": 0.635209,
"n": 120
},
{
"factor": "liquidity_beta",
"proxy": "BTCUSD",
"beta": 0.318435,
"r2": 0.917171,
"n": 120
},
{
"factor": "commodity",
"proxy": "DBC",
"beta": null,
"r2": null,
"n": 0,
"note": "proxy DBC unavailable or short"
},
{
"factor": "real_assets",
"proxy": "GLD",
"beta": null,
"r2": null,
"n": 0,
"note": "proxy GLD unavailable or short"
}
],
"vulnerabilities": [
{
"factor": "equity_beta",
"exposure": 0.55,
"scenario_sensitivity": -2,
"pain": 1.1,
"note": "net long equity_beta; scenario expects equity_beta down (-2)"
},
{
"factor": "duration",
"exposure": 0.3,
"scenario_sensitivity": -1,
"pain": 0.3,
"note": "net long duration; scenario expects duration down (-1)"
},
{
"factor": "credit",
"exposure": 0.15,
"scenario_sensitivity": -2,
"pain": 0.3,
"note": "net long credit; scenario expects credit down (-2)"
}
],
"inputs_digest": "10f7e77fbbec4240ac6e203bf443a6ee03fb19184dceec2950774c066796f8c6",
"would_change": [
"reducing net equity_beta exposure toward zero removes the top vulnerability",
"a regime or market-state transition reselects the scenario stress vector"
],
"notes": [
"decision aid with stated scenario priors; not a covariance risk model and not a VaR claim"
]
},
"digest": "d277793511a0dcda199889d8beedbe849146cf0fc4cb216ce1dc77cadf20b237",
"signature": "416c38e1ed67583d2cff5b8c4020accd9d550eb49dde5956af750f4dae5b0d0ca994f564fe3db7b4a40aaab062b6236f0f8962ee5a4f4d9d00fde5400ef64506",
"verification_key": "e324c4149db27151f65df25d528d3037d3b3bc4165b0d28c0769369cba958ae3"
}
],
"journal": [
{
"payload": {
"schema": "scopeblind.macro.journal-entry/1",
"engine_version": "macro-engine/0.1.0",
"as_of": "2025-08-23",
"author": "demo-model",
"note": "Regime read stagflation while the daily tape printed stress. Cut gross and lengthened nothing; the book is long the wrong factors here.",
"references": [
{
"schema": "scopeblind.macro.market-state/1",
"as_of": "2025-08-23",
"digest": "f469ddc93ce803456bf6eed265c1ffa94690bb3ed972e9dff95c7dab52972e94"
},
{
"schema": "scopeblind.macro.vulnerability/1",
"as_of": "2025-08-23",
"digest": "d277793511a0dcda199889d8beedbe849146cf0fc4cb216ce1dc77cadf20b237"
},
{
"schema": "scopeblind.macro.regime-snapshot/1",
"as_of": "2026-05-01",
"digest": "27a4b9dd293ae77487e919adbf428e4911da62907c39dd017c50376ad9e77591"
}
],
"tags": [
"risk-off",
"stagflation",
"vulnerability"
]
},
"digest": "95415964066eaf10e5de3e49dd18763c8c7d79099baa0bbe670b402f52243923",
"signature": "adce443ba5de6d2e2edea9b5cc19744ae0a7842ad552860c03e895e5393434f4f0448bb5eb5d81f2aae7cbf222494931bfcab30ad465931f073ca2350e042b0c",
"verification_key": "e324c4149db27151f65df25d528d3037d3b3bc4165b0d28c0769369cba958ae3"
}
],
"manifest": {
"payload": {
"schema": "scopeblind.macro.track-record-manifest/1",
"engine_version": "macro-engine/0.1.0",
"exported_at": "2026-05-01T00:00:00Z",
"model_verification_key": "e324c4149db27151f65df25d528d3037d3b3bc4165b0d28c0769369cba958ae3",
"period": {
"from": "2025-01-02",
"to": "2026-05-01"
},
"entries": [
{
"schema": "scopeblind.macro.market-state/1",
"as_of": "2025-08-23",
"digest": "f469ddc93ce803456bf6eed265c1ffa94690bb3ed972e9dff95c7dab52972e94"
},
{
"schema": "scopeblind.macro.tape-snapshot/1",
"as_of": "2025-08-23",
"digest": "43e98d770cb3b4e47c915164d7fe0aa7ec257968978a5cd1aa914e9e2403decd"
},
{
"schema": "scopeblind.macro.regime-snapshot/1",
"as_of": "2026-05-01",
"digest": "27a4b9dd293ae77487e919adbf428e4911da62907c39dd017c50376ad9e77591"
},
{
"schema": "scopeblind.macro.vulnerability/1",
"as_of": "2025-08-23",
"digest": "d277793511a0dcda199889d8beedbe849146cf0fc4cb216ce1dc77cadf20b237"
},
{
"schema": "scopeblind.macro.journal-entry/1",
"as_of": "2025-08-23",
"digest": "95415964066eaf10e5de3e49dd18763c8c7d79099baa0bbe670b402f52243923"
}
],
"snapshot_count": 4,
"journal_count": 1,
"history_head_digest": "15fdd1acd962b562e05b73ca37b9ce3cce064b072fee5b27528edc9cd61eb62f",
"sequence": 1,
"previous_manifest_digest": null,
"previous_history_head_digest": null
},
"digest": "e5697c073e213bc94b2e73a53a2bd140f80821b905daf4e547a9c5674f29643f",
"signature": "c7356a7845c73f0c055144c9e784c8b77826ed85cd6e6271acf2a2c5e4b60be8131bb78a0a914e58de57bc9c0294753700b5ae1f5d72ddf4af494a7a2b8e2e0f",
"verification_key": "e324c4149db27151f65df25d528d3037d3b3bc4165b0d28c0769369cba958ae3"
},
"prior_manifests": [],
"anchor_chain": [
{
"payload": {
"schema": "scopeblind.macro.track-record-anchor/1",
"engine_version": "macro-engine/0.1.0",
"anchored_at": "2026-05-01T00:00:00Z",
"sequence": 1,
"manifest_digest": "e5697c073e213bc94b2e73a53a2bd140f80821b905daf4e547a9c5674f29643f",
"history_head_digest": "15fdd1acd962b562e05b73ca37b9ce3cce064b072fee5b27528edc9cd61eb62f",
"previous_anchor_digest": null
},
"digest": "062188f17b7d0ef9d1acb11e4e85b4ab8c61abb5c192c4ce0d7a784bbf7fb07c",
"signature": "b41012fe8a60cf65da5d28368251994e6d51ab81b81427078297aab11aa74f4dcdc163959cf14d742bb7a67a5c1ccccb332cde49a701d570535af2691a4a6d09",
"verification_key": "e324c4149db27151f65df25d528d3037d3b3bc4165b0d28c0769369cba958ae3"
}
],
"transparency": {
"head": {
"payload": {
"schema": "scopeblind.macro.transparency-head/1",
"engine_version": "macro-engine/0.1.0",
"log_id": "scopeblind.macro.demo-log",
"tree_size": 5,
"root_hash": "40efcc8314749f9b68e2d9555e16d6d223dba67069434108808e18249eb46c3c",
"timestamp": "2026-05-01T00:00:00Z",
"previous_root_hash": null
},
"digest": "6fd187a85cb09a7e01f383e6dee761801b044c04e3c518f00473db4edd626e78",
"signature": "629823481769449e85c793ccd06cfe819b60192ae0a0e72f62b6108b3082b66e8fab5f86c7ae738f599b8ec0a079747ecf308b9540168d8fdc59afbc75dfd409",
"verification_key": "e324c4149db27151f65df25d528d3037d3b3bc4165b0d28c0769369cba958ae3"
},
"witness": {
"payload": {
"schema": "scopeblind.macro.transparency-witness/1",
"engine_version": "macro-engine/0.1.0",
"head_digest": "6fd187a85cb09a7e01f383e6dee761801b044c04e3c518f00473db4edd626e78",
"root_hash": "40efcc8314749f9b68e2d9555e16d6d223dba67069434108808e18249eb46c3c",
"tree_size": 5,
"witnessed_at": "2026-05-01T00:00:00Z",
"note": "demo transparency witness (independent dev key)"
},
"digest": "dd0978d2a1aaefa180e346f8b28d64f31c3bdf7f90b3d2c1f632e45c05cac911",
"signature": "87348b1ac8cc85a280cac613489696ece8a6c668d42cb87d5799930b96978aa39ea4598419425b664365a97c8c0c9618b1ab534506264755d6c108178e4c1002",
"verification_key": "f65f4bc4a3a2d5dc899cb8d99682cd8492789c2d73e5f9e939caa3adc875c322"
},
"inclusions": [
{
"digest": "f469ddc93ce803456bf6eed265c1ffa94690bb3ed972e9dff95c7dab52972e94",
"proof": {
"leaf_index": 0,
"tree_size": 5,
"audit_path": [
"5ed6de6f809567a968c710ba86d0737c2f811bcabcddc437a8cfa53f83ffe09f",
"888f0215bbdc34f19b01cfbe9010e5883d2404aec1b1b17fb28c9798f46895df",
"d043a0e988ecdfe94fb63804f73d51365e514243e9a248e2ab16b317ce0b3f8d"
]
}
},
{
"digest": "43e98d770cb3b4e47c915164d7fe0aa7ec257968978a5cd1aa914e9e2403decd",
"proof": {
"leaf_index": 1,
"tree_size": 5,
"audit_path": [
"74d3d8019a6944bbfb0324a1bf9a54e2bf61fb7c46cb43f700df1f158894b5e6",
"888f0215bbdc34f19b01cfbe9010e5883d2404aec1b1b17fb28c9798f46895df",
"d043a0e988ecdfe94fb63804f73d51365e514243e9a248e2ab16b317ce0b3f8d"
]
}
},
{
"digest": "27a4b9dd293ae77487e919adbf428e4911da62907c39dd017c50376ad9e77591",
"proof": {
"leaf_index": 2,
"tree_size": 5,
"audit_path": [
"a5947d673a413432359ca27bb4d2903f119fa05a8770bb3bae40c90f0e019038",
"7c8ed8da587a98ec9a30df018b41bd793f33a938459fdfa96c549abcd0f05f85",
"d043a0e988ecdfe94fb63804f73d51365e514243e9a248e2ab16b317ce0b3f8d"
]
}
},
{
"digest": "d277793511a0dcda199889d8beedbe849146cf0fc4cb216ce1dc77cadf20b237",
"proof": {
"leaf_index": 3,
"tree_size": 5,
"audit_path": [
"31f0efb1db7235d4c11de485b83bbb9a9989a38069b24f443835a73b118fca22",
"7c8ed8da587a98ec9a30df018b41bd793f33a938459fdfa96c549abcd0f05f85",
"d043a0e988ecdfe94fb63804f73d51365e514243e9a248e2ab16b317ce0b3f8d"
]
}
},
{
"digest": "95415964066eaf10e5de3e49dd18763c8c7d79099baa0bbe670b402f52243923",
"proof": {
"leaf_index": 4,
"tree_size": 5,
"audit_path": [
"43feda61a2b32f67b92add7d712447aa9ddcc96af2bda2553b5cca926cfdc897"
]
}
}
]
}
}
{
"payload": {
"schema": "scopeblind.macro.transparency-head/1",
"engine_version": "macro-engine/0.1.0",
"log_id": "scopeblind.macro.demo-log",
"tree_size": 5,
"root_hash": "40efcc8314749f9b68e2d9555e16d6d223dba67069434108808e18249eb46c3c",
"timestamp": "2026-05-01T00:00:00Z",
"previous_root_hash": null
},
"digest": "6fd187a85cb09a7e01f383e6dee761801b044c04e3c518f00473db4edd626e78",
"signature": "629823481769449e85c793ccd06cfe819b60192ae0a0e72f62b6108b3082b66e8fab5f86c7ae738f599b8ec0a079747ecf308b9540168d8fdc59afbc75dfd409",
"verification_key": "e324c4149db27151f65df25d528d3037d3b3bc4165b0d28c0769369cba958ae3"
}
{
"payload": {
"schema": "scopeblind.macro.transparency-witness/1",
"engine_version": "macro-engine/0.1.0",
"head_digest": "6fd187a85cb09a7e01f383e6dee761801b044c04e3c518f00473db4edd626e78",
"root_hash": "40efcc8314749f9b68e2d9555e16d6d223dba67069434108808e18249eb46c3c",
"tree_size": 5,
"witnessed_at": "2026-05-01T00:00:00Z",
"note": "demo transparency witness (independent dev key)"
},
"digest": "dd0978d2a1aaefa180e346f8b28d64f31c3bdf7f90b3d2c1f632e45c05cac911",
"signature": "87348b1ac8cc85a280cac613489696ece8a6c668d42cb87d5799930b96978aa39ea4598419425b664365a97c8c0c9618b1ab534506264755d6c108178e4c1002",
"verification_key": "f65f4bc4a3a2d5dc899cb8d99682cd8492789c2d73e5f9e939caa3adc875c322"
}
{
"payload": {
"schema": "scopeblind.macro.vulnerability/1",
"engine_version": "macro-engine/0.1.0",
"as_of": "2025-08-23",
"posture": {
"regime": "stagflation",
"market_state": "stress",
"refs": [
{
"schema": "scopeblind.macro.market-state/1",
"as_of": "2025-08-23",
"digest": "f469ddc93ce803456bf6eed265c1ffa94690bb3ed972e9dff95c7dab52972e94"
},
{
"schema": "scopeblind.macro.tape-snapshot/1",
"as_of": "2025-08-23",
"digest": "43e98d770cb3b4e47c915164d7fe0aa7ec257968978a5cd1aa914e9e2403decd"
},
{
"schema": "scopeblind.macro.regime-snapshot/1",
"as_of": "2026-05-01",
"digest": "27a4b9dd293ae77487e919adbf428e4911da62907c39dd017c50376ad9e77591"
}
]
},
"factor_exposures": [
{
"factor": "equity_beta",
"net": 0.55,
"gross": 0.55,
"contributors": [
{
"symbol": "SPY",
"weight": 0.45
},
{
"symbol": "EEM",
"weight": 0.1
}
]
},
{
"factor": "duration",
"net": 0.3,
"gross": 0.3,
"contributors": [
{
"symbol": "IEF",
"weight": 0.3
}
]
},
{
"factor": "credit",
"net": 0.15,
"gross": 0.15,
"contributors": [
{
"symbol": "HYG",
"weight": 0.15
}
]
},
{
"factor": "usd_sensitivity",
"net": 0.1,
"gross": 0.1,
"contributors": [
{
"symbol": "EEM",
"weight": 0.1
}
]
},
{
"factor": "global",
"net": 0.1,
"gross": 0.1,
"contributors": [
{
"symbol": "EEM",
"weight": 0.1
}
]
}
],
"betas": [
{
"factor": "equity_beta",
"proxy": "SPY",
"beta": 0.562937,
"r2": 0.926912,
"n": 120
},
{
"factor": "duration",
"proxy": "IEF",
"beta": -1.916486,
"r2": 0.368425,
"n": 120
},
{
"factor": "credit",
"proxy": "HYG",
"beta": 0.344651,
"r2": 0.727716,
"n": 120
},
{
"factor": "usd",
"proxy": "UUP",
"beta": -1.562837,
"r2": 0.635209,
"n": 120
},
{
"factor": "liquidity_beta",
"proxy": "BTCUSD",
"beta": 0.318435,
"r2": 0.917171,
"n": 120
},
{
"factor": "commodity",
"proxy": "DBC",
"beta": null,
"r2": null,
"n": 0,
"note": "proxy DBC unavailable or short"
},
{
"factor": "real_assets",
"proxy": "GLD",
"beta": null,
"r2": null,
"n": 0,
"note": "proxy GLD unavailable or short"
}
],
"vulnerabilities": [
{
"factor": "equity_beta",
"exposure": 0.55,
"scenario_sensitivity": -2,
"pain": 1.1,
"note": "net long equity_beta; scenario expects equity_beta down (-2)"
},
{
"factor": "duration",
"exposure": 0.3,
"scenario_sensitivity": -1,
"pain": 0.3,
"note": "net long duration; scenario expects duration down (-1)"
},
{
"factor": "credit",
"exposure": 0.15,
"scenario_sensitivity": -2,
"pain": 0.3,
"note": "net long credit; scenario expects credit down (-2)"
}
],
"inputs_digest": "10f7e77fbbec4240ac6e203bf443a6ee03fb19184dceec2950774c066796f8c6",
"would_change": [
"reducing net equity_beta exposure toward zero removes the top vulnerability",
"a regime or market-state transition reselects the scenario stress vector"
],
"notes": [
"decision aid with stated scenario priors; not a covariance risk model and not a VaR claim"
]
},
"digest": "d277793511a0dcda199889d8beedbe849146cf0fc4cb216ce1dc77cadf20b237",
"signature": "416c38e1ed67583d2cff5b8c4020accd9d550eb49dde5956af750f4dae5b0d0ca994f564fe3db7b4a40aaab062b6236f0f8962ee5a4f4d9d00fde5400ef64506",
"verification_key": "e324c4149db27151f65df25d528d3037d3b3bc4165b0d28c0769369cba958ae3"
}
/**
* Legate adherence / restraint proof pack verifier.
*
* A proof pack (type "scopeblind.legate.proof-pack.v1") is the allocator-facing,
* POSITION-BLIND record a Legate desk produces: what the gate prevented over a
* session (held / blocked, attributed to rules), what the order-path shadow would
* have blocked, and the digests it is bound to (committed mandate, signed book
* provenance, receipt Merkle root). It carries its own runtime verification key, so
* a third party re-verifies it offline with nothing but this CLI.
*
* Signature recipe (legate-proof-pack.cjs signProofPack): Ed25519 over the UTF-8
* bytes of the canonical (deep-sorted, no-whitespace) JSON of the pack MINUS its
* `signature`, `sha256`, and `hybrid_signature` fields; `sha256` is that canonical's
* SHA-256 digest. The runtime public key is `verification_key` (and runtime.
* verification_key), raw 32-byte hex. Signing is over the bytes directly, like the
* Legate governed receipt, NOT over a pre-hash like the Gate tuple.
*
* @module verify-cli/src/engines/legate-proof-pack
*/
import { ed25519 } from '@noble/curves/ed25519';
import { sha256 } from '@noble/hashes/sha256';
import { utf8ToBytes } from '@noble/hashes/utils';
import { canonicalize } from '../util/canonical.js';
import { hexToBytes, bytesToHex } from '../util/hex.js';
export const PROOF_PACK_TYPE = 'scopeblind.legate.proof-pack.v1';
const isString = (v) => typeof v === 'string' && v.length > 0;
const HEX = (s) => typeof s === 'string' && /^[0-9a-f]+$/i.test(s) && s.length % 2 === 0;
const num = (v) => (Number.isFinite(Number(v)) ? Number(v) : 0);
const PROVES = [
'The pack was signed by the holder of the runtime key (verification_key) and not altered since: every field is bound by the Ed25519 signature over the canonical bytes.',
'The restraint counts (held / blocked, by rule) and the order-path shadow counts are the runtime\'s own, attributed to the committed mandate digest.',
'The artifact is position-blind: it contains digests and counts only, never positions, so adherence is verifiable without disclosing the book.',
];
const LIMITATIONS = [
'That the underlying receipts behind the Merkle root and the signed book behind book.sha256 are themselves correct, unless those are separately verified.',
'That the runtime key belongs to the desk you expect; pin it with --key to bind the pack to a known runtime.',
];
/**
* Reconstruct the exact canonical string that was signed: the pack minus the
* signature, the bound digest, and any hybrid signature.
*/
export function proofPackSignedCanonical(pack) {
const { signature, sha256: _digest, hybrid_signature, ...rest } = pack;
return canonicalize(rest);
}
/**
* @param {object} pack the proof pack envelope
* @param {object} opts { publicKey?: pinned runtime key (hex) }
*/
export function verifyLegateProofPack(pack, opts = {}) {
const base = {
format: 'legate-proof-pack',
schema: isString(pack?.type) ? pack.type : PROOF_PACK_TYPE,
algorithm: 'ed25519',
};
if (pack === null || typeof pack !== 'object' || Array.isArray(pack)) {
return { valid: false, error: 'unknown_format', ...base, detail: 'proof pack is not an object' };
}
if (pack.type !== PROOF_PACK_TYPE) {
return { valid: false, error: 'unknown_format', ...base, detail: `type is not ${PROOF_PACK_TYPE}` };
}
const vk = isString(pack.verification_key)
? pack.verification_key
: (pack.runtime && isString(pack.runtime.verification_key) ? pack.runtime.verification_key : undefined);
if (!isString(pack.signature)) return { valid: false, error: 'missing_signature', ...base };
if (!isString(vk)) return { valid: false, error: 'no_public_key', ...base };
if (!HEX(pack.signature) || !HEX(vk)) {
return { valid: false, error: 'malformed_hex', ...base, detail: 'signature and verification_key must be hex' };
}
const pinned = isString(opts.publicKey);
if (pinned && opts.publicKey.toLowerCase() !== vk.toLowerCase()) {
return { valid: false, error: 'key_mismatch', ...base, publicKey: vk, expectedKey: opts.publicKey };
}
// The bound digest must match the canonical the signature covers.
const canonical = proofPackSignedCanonical(pack);
if (isString(pack.sha256)) {
const recomputed = bytesToHex(sha256(utf8ToBytes(canonical)));
if (recomputed !== pack.sha256) {
return { valid: false, error: 'digest_mismatch', ...base, detail: 'sha256 does not match the canonical bytes (the pack was modified after signing)', publicKey: vk };
}
}
let ok = false;
try {
ok = ed25519.verify(hexToBytes(pack.signature), utf8ToBytes(canonical), hexToBytes(vk));
} catch (e) {
return { valid: false, error: 'malformed_hex', ...base, detail: e.message, publicKey: vk };
}
if (!ok) {
return { valid: false, error: 'invalid_signature', ...base, publicKey: vk };
}
const mandate = pack.mandate || {};
const restraint = pack.restraint || {};
const shadow = pack.shadow || null;
const book = pack.book || {};
return {
valid: true,
...base,
publicKey: vk,
keySource: pinned ? 'embedded-pack (pinned via --key)' : 'embedded-pack',
signerKid: isString(pack.signer_kid) ? pack.signer_kid : undefined,
generatedAt: isString(pack.generated_at) ? pack.generated_at : undefined,
positionBlind: pack.position_blind !== false,
mandate: { name: mandate.name, sha256: mandate.sha256, mode: mandate.mode, ruleCount: num(mandate.rule_count) },
restraint: { blocked: num(restraint.blocked), held: num(restraint.held), byRule: Array.isArray(restraint.by_rule) ? restraint.by_rule : [] },
shadow: shadow ? { observed: num(shadow.observed), wouldBlock: num(shadow.would_block), wouldHold: num(shadow.would_hold) } : null,
bookDigest: isString(book.sha256) ? book.sha256 : null,
sessionMerkleRoot: isString(pack.session_merkle_root) ? pack.session_merkle_root : null,
receiptCount: num(pack.receipt_count),
// A hybrid post-quantum signature, when present, is recognized and reported.
// Classical Ed25519 is verified here; ML-DSA-65 verification is an optional add-on
// (the runtime is dependency-free and signs classically; PQ is documented in the
// restraint-receipts draft as an optional field for surfaces that can produce it).
hybridSignaturePresent: Boolean(pack.hybrid_signature),
proves: PROVES,
limitations: LIMITATIONS,
};
}
/**
* ScopeBlind macro-engine snapshot and track-record verifier.
*
* The macro engine signs its snapshots (market-state, regime, tape,
* vulnerability, alert, journal) and its exported track-record bundle with
* the EXACT same tuple format the Gate uses: { payload, digest, signature,
* verification_key }, where digest = sha256(canonicalGateJSON(payload)) and
* signature = Ed25519 over the bytes of the hex digest.
*
* These tuples already verify cryptographically through
* engines/gate-receipt.js verifyGateTuple. This module ADDS:
* - recognition of the scopeblind.macro.* schemas,
* - a semantic-contract check per schema (macroSchemaErrors),
* - a schema-aware salient-field summary for display (macroSummary),
* - a track-record BUNDLE verifier (verifyMacroTrackRecord) that mirrors
* verifyGateBundle: every record's signature, single-signer custody, an
* exact manifest inventory, count checks, and the history_head_digest.
*
* No new cryptography is introduced. Crypto is delegated to verifyGateTuple
* and canonicalization to canonicalGateJSON, both from gate-receipt.js.
*
* @module verify-cli/src/engines/macro-snapshot
* @license Apache-2.0
*/
import { sha256 } from '@noble/hashes/sha256';
import { utf8ToBytes, bytesToHex } from '@noble/hashes/utils';
import { canonicalGateJSON, verifyGateTuple } from './gate-receipt.js';
export const MACRO_BUNDLE_SCHEMA = 'scopeblind.macro.track-record-bundle/1';
export const MACRO_MANIFEST_SCHEMA = 'scopeblind.macro.track-record-manifest/1';
export const MACRO_ANCHOR_SCHEMA = 'scopeblind.macro.track-record-anchor/1';
export const MACRO_TRANSPARENCY_HEAD_SCHEMA = 'scopeblind.macro.transparency-head/1';
export const MACRO_TRANSPARENCY_WITNESS_SCHEMA = 'scopeblind.macro.transparency-witness/1';
export const MACRO_SCHEMA_PREFIX = 'scopeblind.macro.';
/** Human descriptions for every recognized macro schema. */
export const MACRO_SCHEMAS = {
'scopeblind.macro.market-state/1': 'daily cross-asset market-state classification',
'scopeblind.macro.regime-snapshot/1': 'macro regime snapshot from economic series',
'scopeblind.macro.tape-snapshot/1': 'intraday/session tape attribution snapshot',
'scopeblind.macro.vulnerability/1': 'book vulnerability decision aid',
'scopeblind.macro.alert/1': 'state-change alert',
'scopeblind.macro.journal-entry/1': 'model journal entry referencing snapshots',
'scopeblind.macro.price-snapshot/1': 'signed point-in-time price levels per risk factor',
[MACRO_MANIFEST_SCHEMA]: 'signed track-record export manifest',
[MACRO_ANCHOR_SCHEMA]: 'signed append-only track-record checkpoint',
[MACRO_TRANSPARENCY_HEAD_SCHEMA]: 'signed RFC 6962 transparency-log head over snapshot digests',
[MACRO_TRANSPARENCY_WITNESS_SCHEMA]: 'independent witness co-signature over a transparency-log head',
};
const HEX_64 = /^[0-9a-f]{64}$/;
const MARKET_STATE_CLASSES = new Set(['risk_on', 'constructive', 'mixed', 'deteriorating', 'stress']);
const MARKET_STATE_PILLARS = ['trend', 'breadth', 'liquidity', 'credit', 'volatility'];
const REGIMES = new Set(['goldilocks', 'reflation', 'stagflation', 'deflation_bust', 'liquidity_led_recovery', 'tightening_squeeze', 'transitional']);
const TAPE_TYPES = new Set(['credit_stress', 'tightening_shock', 'growth_scare', 'inflation_shock', 'liquidity_risk_on', 'reflation_risk_on', 'mixed']);
const ALERT_SEVERITIES = new Set(['info', 'action', 'critical']);
const ALERT_KINDS = new Set(['regime_transition', 'market_state_change', 'tape_type_change']);
const isObject = (v) => v !== null && typeof v === 'object' && !Array.isArray(v);
const isString = (v) => typeof v === 'string' && v.length > 0;
const isNumber = (v) => typeof v === 'number' && Number.isFinite(v);
const isInteger = (v) => Number.isInteger(v);
const isArray = (v) => Array.isArray(v);
/** Whether a schema string is a recognized macro snapshot/journal/manifest schema. */
export function isMacroSchema(schema) {
return typeof schema === 'string' && schema.startsWith(MACRO_SCHEMA_PREFIX);
}
/** A market-state/regime/tape/etc snapshot proves authenticity + integrity + schema validity. */
export const MACRO_PROVES = [
'Signature integrity: the snapshot verifies under its carried Ed25519 key.',
'Integrity: neither payload nor digest has been modified since signing.',
'Schema validity: the recognized macro snapshot satisfies its required semantic contract.',
];
export const MACRO_LIMITATIONS = [
'The real-world identity controlling the carried key unless the expected key is independently pinned with --key.',
'Correctness of the underlying market or economic series the snapshot was computed from.',
'That the classification, regime, or tape attribution is a good or predictive read of the market.',
'Independent corroboration of the inputs unless separately attested; the model signs what it computed.',
];
export const MACRO_BUNDLE_PROVES = [
'Signature integrity: every included snapshot, journal entry, manifest, and anchor verifies under one Ed25519 key.',
'Integrity: no record payload or digest has been modified since signing.',
'Single-key consistency: all records, including the manifest, share one model verification key.',
'Manifest completeness: the signed manifest exactly enumerates every exported snapshot and journal entry, in order.',
'History binding: the manifest history_head_digest commits to the exact ordered set of record digests.',
];
export const MACRO_BUNDLE_LIMITATIONS = [
'Correctness of the underlying market or economic data the snapshots were computed from.',
'That the recorded calls were good predictions; the bundle is a tamper-evident track record, not a performance claim.',
'The real-world identity controlling an embedded key unless the expected key is independently pinned with --key.',
'Global history completeness unless prior manifests are chained and the latest history/anchor head is independently retained or timestamped.',
];
function requireFields(payload, fields, errors) {
for (const field of fields) {
if (payload[field] === undefined || payload[field] === null || payload[field] === '') errors.push(`missing ${field}`);
}
}
/** Validate an array of { schema, as_of, digest } reference objects with 64-hex digests. */
function refErrors(refs, label, errors, { nonEmpty = true } = {}) {
if (!isArray(refs)) { errors.push(`${label} must be an array`); return; }
if (nonEmpty && refs.length === 0) { errors.push(`${label} must be non-empty`); return; }
for (const ref of refs) {
if (!isObject(ref) || !isString(ref.schema) || !isString(ref.as_of) || !HEX_64.test(ref.digest || '')) {
errors.push(`${label} entry must be { schema, as_of, digest(64-hex) }`);
break;
}
}
}
/**
* Semantic-contract validation for a recognized macro payload.
* Returns [] for valid payloads and for unrecognized (non-macro or unknown
* macro) schemas; returns one or more human-readable error strings otherwise.
*
* @param {Object} payload signed macro payload
* @returns {string[]}
*/
export function macroSchemaErrors(payload) {
const errors = [];
if (!isObject(payload)) return errors;
const schema = payload.schema;
if (!Object.hasOwn(MACRO_SCHEMAS, schema)) return errors;
if (schema === 'scopeblind.macro.market-state/1') {
requireFields(payload, ['schema', 'engine_version', 'as_of', 'universe_digest', 'inputs_digest', 'pillars', 'evidence', 'classification', 'confidence', 'would_change', 'notes'], errors);
if (!MARKET_STATE_CLASSES.has(payload.classification)) errors.push('invalid classification');
if (!isObject(payload.pillars)) errors.push('pillars must be an object');
else {
for (const p of MARKET_STATE_PILLARS) {
if (!isInteger(payload.pillars[p]) || payload.pillars[p] < -2 || payload.pillars[p] > 2) errors.push(`invalid pillar ${p} (integer in [-2,2])`);
}
}
if (!isNumber(payload.confidence) || payload.confidence < 0 || payload.confidence > 1) errors.push('confidence must be a number in [0,1]');
} else if (schema === 'scopeblind.macro.regime-snapshot/1') {
requireFields(payload, ['schema', 'engine_version', 'as_of', 'pillars', 'inputs', 'vintage_digest', 'candidate_regime', 'regime', 'liquidity_overlay', 'hysteresis', 'playbook', 'confidence', 'would_change', 'notes'], errors);
if (!REGIMES.has(payload.regime)) errors.push('invalid regime');
if (!REGIMES.has(payload.candidate_regime)) errors.push('invalid candidate_regime');
if (!HEX_64.test(payload.vintage_digest || '')) errors.push('invalid vintage_digest');
if (!isObject(payload.pillars)) errors.push('pillars must be an object');
if (!isArray(payload.inputs)) errors.push('inputs must be an array');
if (!isNumber(payload.confidence) || payload.confidence < 0 || payload.confidence > 1) errors.push('confidence must be a number in [0,1]');
} else if (schema === 'scopeblind.macro.tape-snapshot/1') {
requireFields(payload, ['schema', 'engine_version', 'as_of', 'session', 'tape_type', 'coherence', 'material', 'signals', 'unavailable', 'untestable_types', 'attribution', 'inputs_digest', 'would_change', 'notes'], errors);
if (!TAPE_TYPES.has(payload.tape_type)) errors.push('invalid tape_type');
if (!isNumber(payload.coherence) || payload.coherence < 0 || payload.coherence > 1) errors.push('coherence must be a number in [0,1]');
if (typeof payload.material !== 'boolean') errors.push('material must be a boolean');
if (!isArray(payload.signals)) errors.push('signals must be an array');
if (!isObject(payload.attribution) || !isString(payload.attribution.tier)) errors.push('attribution must carry a tier');
} else if (schema === 'scopeblind.macro.vulnerability/1') {
requireFields(payload, ['schema', 'engine_version', 'as_of', 'posture', 'factor_exposures', 'betas', 'vulnerabilities', 'inputs_digest', 'would_change', 'notes'], errors);
if (!isObject(payload.posture)) errors.push('posture must be an object');
if (!isArray(payload.factor_exposures)) errors.push('factor_exposures must be an array');
if (!isArray(payload.betas)) errors.push('betas must be an array');
if (!isArray(payload.vulnerabilities)) errors.push('vulnerabilities must be an array');
} else if (schema === 'scopeblind.macro.alert/1') {
requireFields(payload, ['schema', 'engine_version', 'as_of', 'alert_id', 'kind', 'severity', 'title', 'detail', 'refs', 'budget'], errors);
if (!HEX_64.test(payload.alert_id || '')) errors.push('invalid alert_id');
if (!ALERT_SEVERITIES.has(payload.severity)) errors.push('invalid severity');
if (!ALERT_KINDS.has(payload.kind)) errors.push('invalid kind');
refErrors(payload.refs, 'refs', errors);
} else if (schema === 'scopeblind.macro.journal-entry/1') {
requireFields(payload, ['schema', 'engine_version', 'as_of', 'author', 'note', 'references', 'tags'], errors);
if (!isArray(payload.tags)) errors.push('tags must be an array');
refErrors(payload.references, 'references', errors);
} else if (schema === 'scopeblind.macro.price-snapshot/1') {
requireFields(payload, ['schema', 'engine_version', 'as_of', 'source', 'delay_minutes', 'levels', 'coverage', 'missing', 'notes'], errors);
if (!isInteger(payload.delay_minutes) || payload.delay_minutes < 0) errors.push('delay_minutes must be a non-negative integer');
if (!isString(payload.source)) errors.push('source must be a non-empty string');
if (!isArray(payload.coverage)) errors.push('coverage must be an array');
if (!isArray(payload.missing)) errors.push('missing must be an array');
if (!isObject(payload.levels)) {
errors.push('levels must be an object');
} else {
const factors = Object.keys(payload.levels);
if (factors.length === 0) errors.push('levels must price at least one factor');
const VALID_UNITS = new Set(['price', 'yield_pct', 'fx_rate', 'spread_bp']);
for (const f of factors) {
const lv = payload.levels[f];
if (!isObject(lv)) { errors.push(`level ${f} must be an object`); continue; }
if (!isNumber(lv.level)) errors.push(`level ${f} must carry a numeric level`);
if (!isString(lv.instrument)) errors.push(`level ${f} must name an instrument`);
if (!VALID_UNITS.has(lv.unit)) errors.push(`level ${f} has invalid unit`);
if (lv.multiplier !== undefined && (!isNumber(lv.multiplier) || lv.multiplier <= 0)) errors.push(`level ${f} multiplier must be a positive number`);
}
// coverage must list exactly the priced factors (sorted), never overstate.
if (isArray(payload.coverage)) {
const cov = [...payload.coverage].sort();
const keys = [...factors].sort();
if (cov.length !== keys.length || cov.some((c, i) => c !== keys[i])) errors.push('coverage must list exactly the priced factors');
}
}
} else if (schema === MACRO_MANIFEST_SCHEMA) {
requireFields(payload, ['schema', 'engine_version', 'exported_at', 'model_verification_key', 'period', 'entries', 'snapshot_count', 'journal_count', 'history_head_digest'], errors);
if (!HEX_64.test(payload.model_verification_key || '')) errors.push('invalid model_verification_key');
if (!HEX_64.test(payload.history_head_digest || '')) errors.push('invalid history_head_digest');
refErrors(payload.entries, 'entries', errors, { nonEmpty: false });
if (payload.sequence !== undefined && (!isInteger(payload.sequence) || payload.sequence < 1)) errors.push('sequence must be a positive integer');
} else if (schema === MACRO_ANCHOR_SCHEMA) {
requireFields(payload, ['schema', 'engine_version', 'anchored_at', 'sequence', 'manifest_digest', 'history_head_digest'], errors);
if (!isInteger(payload.sequence) || payload.sequence < 1) errors.push('sequence must be a positive integer');
if (!HEX_64.test(payload.manifest_digest || '')) errors.push('invalid manifest_digest');
if (!HEX_64.test(payload.history_head_digest || '')) errors.push('invalid history_head_digest');
if (payload.previous_anchor_digest !== null && !HEX_64.test(payload.previous_anchor_digest || '')) errors.push('invalid previous_anchor_digest');
} else if (schema === MACRO_TRANSPARENCY_HEAD_SCHEMA) {
requireFields(payload, ['schema', 'engine_version', 'log_id', 'tree_size', 'root_hash', 'timestamp'], errors);
if (!isInteger(payload.tree_size) || payload.tree_size < 0) errors.push('tree_size must be a non-negative integer');
if (!HEX_64.test(payload.root_hash || '')) errors.push('invalid root_hash');
// previous_root_hash is a required key but is null at the genesis head.
if (!Object.hasOwn(payload, 'previous_root_hash')) errors.push('missing previous_root_hash');
else if (payload.previous_root_hash !== null && !HEX_64.test(payload.previous_root_hash || '')) errors.push('invalid previous_root_hash');
} else if (schema === MACRO_TRANSPARENCY_WITNESS_SCHEMA) {
requireFields(payload, ['schema', 'engine_version', 'head_digest', 'root_hash', 'tree_size', 'witnessed_at', 'note'], errors);
if (!HEX_64.test(payload.head_digest || '')) errors.push('invalid head_digest');
if (!HEX_64.test(payload.root_hash || '')) errors.push('invalid root_hash');
if (!isInteger(payload.tree_size) || payload.tree_size < 0) errors.push('tree_size must be a non-negative integer');
}
return errors;
}
/**
* Extract the salient display fields for a recognized macro snapshot.
* Returns null for unrecognized schemas.
*
* @param {Object} payload signed macro payload
* @returns {Object|null}
*/
export function macroSummary(payload) {
if (!isObject(payload) || !Object.hasOwn(MACRO_SCHEMAS, payload.schema)) return null;
const schema = payload.schema;
const base = { schema, description: MACRO_SCHEMAS[schema], as_of: payload.as_of };
if (schema === 'scopeblind.macro.market-state/1') {
return { ...base, classification: payload.classification, pillars: payload.pillars, confidence: payload.confidence };
}
if (schema === 'scopeblind.macro.regime-snapshot/1') {
return { ...base, regime: payload.regime, candidate_regime: payload.candidate_regime, liquidity_overlay: payload.liquidity_overlay, confidence: payload.confidence };
}
if (schema === 'scopeblind.macro.tape-snapshot/1') {
return { ...base, tape_type: payload.tape_type, coherence: payload.coherence, material: payload.material, attribution_tier: payload.attribution?.tier };
}
if (schema === 'scopeblind.macro.vulnerability/1') {
const top = (isArray(payload.vulnerabilities) ? payload.vulnerabilities : [])
.slice()
.sort((a, b) => (b?.pain ?? 0) - (a?.pain ?? 0))
.slice(0, 3)
.map((v) => ({ factor: v?.factor, pain: v?.pain }));
return { ...base, regime: payload.posture?.regime, market_state: payload.posture?.market_state, top_vulnerabilities: top };
}
if (schema === 'scopeblind.macro.alert/1') {
return { ...base, severity: payload.severity, kind: payload.kind, title: payload.title };
}
if (schema === 'scopeblind.macro.journal-entry/1') {
return { ...base, author: payload.author, reference_count: isArray(payload.references) ? payload.references.length : 0, tags: payload.tags };
}
if (schema === 'scopeblind.macro.price-snapshot/1') {
return {
...base,
source: payload.source,
delay_minutes: payload.delay_minutes,
priced: isArray(payload.coverage) ? payload.coverage.length : 0,
missing: isArray(payload.missing) ? payload.missing.length : 0,
};
}
if (schema === MACRO_MANIFEST_SCHEMA) {
return { ...base, sequence: payload.sequence ?? 1, snapshot_count: payload.snapshot_count, journal_count: payload.journal_count };
}
if (schema === MACRO_ANCHOR_SCHEMA) {
return { ...base, sequence: payload.sequence, manifest_digest: payload.manifest_digest, history_head_digest: payload.history_head_digest };
}
if (schema === MACRO_TRANSPARENCY_HEAD_SCHEMA) {
return { ...base, log_id: payload.log_id, tree_size: payload.tree_size, root_hash: payload.root_hash };
}
if (schema === MACRO_TRANSPARENCY_WITNESS_SCHEMA) {
return { ...base, head_digest: payload.head_digest, tree_size: payload.tree_size };
}
return base;
}
const refsEqual = (a, b) =>
isObject(a) && isObject(b) && a.schema === b.schema && a.as_of === b.as_of && a.digest === b.digest;
// ── RFC 6962 transparency-log inclusion verification ─────────────────
//
// The macro engine signs an RFC 6962 Merkle transparency log over the
// snapshot/journal record digests. This block reconstructs a leaf's root from
// its audit path EXACTLY as the engine builds it, so the verifier can confirm
// that every exported record is committed under the signed head's root_hash.
// Hashing is domain-separated over RAW digest bytes (not the hex string).
/** Decode a hex string to a Uint8Array (no prefix handling; lengths are caller-checked). */
function hexToBytes(hex) {
const bytes = new Uint8Array(hex.length / 2);
for (let i = 0; i < bytes.length; i++) bytes[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
return bytes;
}
/** Concatenate Uint8Arrays into one. */
function concatBytes(...arrays) {
let length = 0;
for (const a of arrays) length += a.length;
const out = new Uint8Array(length);
let offset = 0;
for (const a of arrays) { out.set(a, offset); offset += a.length; }
return out;
}
/** RFC 6962 leaf hash: sha256(0x00 || raw record-digest bytes). */
function leafHash(recordDigestHex) {
return sha256(concatBytes(Uint8Array.of(0x00), hexToBytes(recordDigestHex)));
}
/** RFC 6962 interior node hash: sha256(0x01 || left || right). */
function nodeHash(left, right) {
return sha256(concatBytes(Uint8Array.of(0x01), left, right));
}
/** Largest power of two STRICTLY less than n (RFC 6962 split point). */
function splitPoint(n) {
let k = 1;
while ((k << 1) < n) k <<= 1;
return k;
}
/**
* Verify an RFC 6962 inclusion proof: reconstruct the Merkle root for the leaf
* at proof.leaf_index in a tree of proof.tree_size leaves, consuming the audit
* path deepest-sibling-first (top sibling LAST, i.e. from the END of the array).
*
* @param {string} recordDigestHex 64-hex record digest committed as the leaf
* @param {Object} proof { leaf_index, tree_size, audit_path: string[] }
* @param {string} expectedRootHex 64-hex root_hash from the signed head
* @returns {boolean}
*/
export function verifyInclusion(recordDigestHex, proof, expectedRootHex) {
if (!isObject(proof)) return false;
const { leaf_index, tree_size, audit_path } = proof;
if (!isInteger(leaf_index) || !isInteger(tree_size)) return false;
if (leaf_index < 0 || leaf_index >= tree_size) return false;
if (!HEX_64.test(recordDigestHex || '')) return false;
if (!HEX_64.test(expectedRootHex || '')) return false;
if (!isArray(audit_path) || !audit_path.every((h) => HEX_64.test(h || ''))) return false;
const nodes = audit_path.map(hexToBytes);
// hi = number of path nodes still available; the top sibling is nodes[hi-1].
function root(m, size, hi) {
if (size === 1) return hi === 0 ? leafHash(recordDigestHex) : null;
if (hi < 1) return null;
const k = splitPoint(size);
const sib = nodes[hi - 1];
if (m < k) {
const left = root(m, k, hi - 1);
return left && nodeHash(left, sib);
}
const right = root(m - k, size - k, hi - 1);
return right && nodeHash(sib, right);
}
const r = root(leaf_index, tree_size, nodes.length);
return r !== null && bytesToHex(r) === expectedRootHex;
}
/**
* Verify a track-record bundle's transparency evidence: the signed log head,
* every record's inclusion under that head's root, and (optionally) an
* independent witness co-signature over the same head.
*
* @param {Object} evidence bundle.transparency: { head, witness, inclusions }
* @param {string[]} recordDigests every snapshot + journal record digest that
* must be committed in the log
* @returns {{ head_valid: boolean, all_included: boolean, witness_present: boolean,
* witness_independent: boolean, anchor: 'none'|'self_signed'|'witnessed',
* tree_size: number|null, root_hash: string|null, errors: string[] }}
*/
export function verifyTransparencyEvidence(evidence, recordDigests = []) {
const result = {
head_valid: false,
all_included: false,
witness_present: false,
witness_independent: false,
anchor: 'none',
tree_size: null,
root_hash: null,
errors: [],
};
if (!isObject(evidence) || !isObject(evidence.head)) {
result.errors.push('transparency evidence is missing a signed head');
return result;
}
const head = evidence.head;
const headResult = verifyGateTuple(head);
const headPayload = isObject(head.payload) ? head.payload : {};
const root = headPayload.root_hash;
result.tree_size = isInteger(headPayload.tree_size) ? headPayload.tree_size : null;
result.root_hash = isString(root) ? root : null;
if (!headResult.valid) {
result.errors.push(`transparency head signature invalid: ${headResult.error}`);
} else if (headPayload.schema !== MACRO_TRANSPARENCY_HEAD_SCHEMA) {
result.errors.push('transparency head is not a transparency-head schema');
} else if (!HEX_64.test(root || '')) {
result.errors.push('transparency head root_hash is not 64-hex');
} else {
result.head_valid = true;
}
// Inclusion of every checked record under the signed root.
if (result.head_valid) {
const inclusions = isArray(evidence.inclusions) ? evidence.inclusions : [];
const byDigest = new Map();
for (const inc of inclusions) {
if (isObject(inc) && isString(inc.digest)) byDigest.set(inc.digest.toLowerCase(), inc);
}
let allIncluded = recordDigests.length > 0 || inclusions.length > 0;
for (const digest of recordDigests) {
const inc = byDigest.get(String(digest).toLowerCase());
if (!inc || !verifyInclusion(digest, inc.proof, root)) {
allIncluded = false;
result.errors.push(`record ${String(digest).slice(0, 16)}... is not provably included in the signed log`);
}
}
result.all_included = allIncluded;
}
// Optional independent witness co-signature over the same head.
if (isObject(evidence.witness)) {
result.witness_present = true;
const witness = evidence.witness;
const witnessResult = verifyGateTuple(witness);
const witnessPayload = isObject(witness.payload) ? witness.payload : {};
const witnessValid = witnessResult.valid
&& witnessPayload.schema === MACRO_TRANSPARENCY_WITNESS_SCHEMA
&& witnessPayload.head_digest === head.digest
&& witnessPayload.root_hash === root;
if (!witnessValid) {
result.errors.push('transparency witness does not co-sign this head');
} else {
result.witness_independent = isString(witness.verification_key)
&& isString(head.verification_key)
&& witness.verification_key.toLowerCase() !== head.verification_key.toLowerCase();
}
}
result.anchor = (!result.head_valid || !result.all_included)
? 'none'
: result.witness_independent ? 'witnessed' : 'self_signed';
return result;
}
/**
* Verify a macro track-record bundle.
*
* Mirrors verifyGateBundle: it checks each record's signature, that every
* record (including the manifest) is signed by the single declared model
* key, that the manifest entries exactly enumerate the snapshots followed by
* the journal entries in order, the snapshot/journal counts, and that the
* history_head_digest recomputes over the ordered record digests.
*
* @param {Object} bundle parsed track-record bundle
* @param {Object} [opts] { publicKey } optional pinned model key
* @returns {Object} result with the same error-shape conventions as gate-receipt.js
*/
export function verifyMacroTrackRecord(bundle, opts = {}) {
const results = {
valid: true,
format: 'macro-track-record',
schema: bundle?.schema,
exportedAt: bundle?.exported_at,
period: isObject(bundle?.period) ? bundle.period : null,
custody: isString(bundle?.custody) ? bundle.custody : null,
modelVerificationKey: isString(bundle?.model_verification_key) ? bundle.model_verification_key : null,
snapshotCount: 0,
journalCount: 0,
total: 0,
passed: 0,
failed: 0,
cryptoFailed: 0,
chainChecks: 0,
chainFailed: 0,
errors: [],
records: [],
signers: [],
singleSigner: true,
manifestValid: null,
signerPinned: isString(opts.publicKey),
identityStatus: isString(opts.publicKey) ? 'pinned_operator_key' : 'embedded_key_only',
historyChainValid: null,
historyAnchored: false,
historyHeadPinned: false,
anchorHeadPinned: false,
sequence: 1,
transparencyAnchor: null,
proves: MACRO_BUNDLE_PROVES,
limitations: MACRO_BUNDLE_LIMITATIONS,
};
if (!isObject(bundle) || bundle.schema !== MACRO_BUNDLE_SCHEMA || !isArray(bundle.snapshots) || !isObject(bundle.manifest)) {
return { ...results, valid: false, error: 'unknown_format', detail: 'unsupported macro bundle schema or missing snapshots/manifest' };
}
const snapshots = bundle.snapshots;
const journal = isArray(bundle.journal) ? bundle.journal : [];
const priorManifests = isArray(bundle.prior_manifests) ? bundle.prior_manifests : [];
const anchors = isArray(bundle.anchor_chain) ? bundle.anchor_chain : [];
results.snapshotCount = snapshots.length;
results.journalCount = journal.length;
if (!HEX_64.test(results.modelVerificationKey || '')) {
return { ...results, valid: false, error: 'no_public_key', detail: 'bundle requires model_verification_key' };
}
const modelKey = results.modelVerificationKey.toLowerCase();
if (isString(opts.publicKey) && opts.publicKey.toLowerCase() !== modelKey) {
return { ...results, valid: false, error: 'key_mismatch', detail: 'bundle model_verification_key does not match --key' };
}
const signerRoles = new Map();
let firstError = null;
const add = (tuple, role, index) => {
results.total++;
const r = verifyGateTuple(tuple, { publicKey: modelKey });
const key = isString(tuple?.verification_key) ? tuple.verification_key.toLowerCase() : null;
if (key) {
if (!signerRoles.has(key)) signerRoles.set(key, new Set());
signerRoles.get(key).add(role);
if (key !== modelKey) results.singleSigner = false;
} else {
results.singleSigner = false;
}
const record = {
index: index + 1,
role,
schema: r.schema,
schemaRecognized: r.schemaRecognized || isMacroSchema(r.schema),
cryptoValid: r.valid,
cryptoError: r.valid ? undefined : r.error,
signer: tuple?.verification_key,
digest: tuple?.digest,
};
results.records.push(record);
if (!r.valid) {
results.cryptoFailed++;
results.valid = false;
firstError ||= r.error;
results.errors.push(`[crypto] ${role} ${index + 1}: ${r.error}${r.detail ? ` (${r.detail})` : ''}`);
results.failed++;
} else {
results.passed++;
}
return r;
};
for (let i = 0; i < snapshots.length; i++) add(snapshots[i], 'snapshot', i);
for (let i = 0; i < journal.length; i++) add(journal[i], 'journal', i);
for (let i = 0; i < priorManifests.length; i++) add(priorManifests[i], 'prior-manifest', i);
const mr = add(bundle.manifest, 'manifest', -1);
for (let i = 0; i < anchors.length; i++) add(anchors[i], 'history-anchor', i);
results.manifestValid = mr.valid;
// Single-signer custody check (every record, including the manifest, shares
// the declared model key).
results.chainChecks++;
if (!results.singleSigner) {
results.valid = false;
results.chainFailed++;
results.errors.push('[chain] not all records are signed by model_verification_key (single-signer custody violated)');
}
// Manifest inventory + counts + history head.
if (mr.valid) {
const p = bundle.manifest.payload;
const ordered = [...snapshots, ...journal];
const expectedEntries = ordered.map((t) => ({ schema: t?.payload?.schema, as_of: t?.payload?.as_of, digest: t?.digest }));
const historyHead = bytesToHex(sha256(utf8ToBytes(canonicalGateJSON(ordered.map((t) => t?.digest)))));
results.chainChecks++;
const entries = isArray(p.entries) ? p.entries : [];
let manifestError = null;
if (p.model_verification_key?.toLowerCase() !== modelKey) manifestError = 'manifest model_verification_key mismatch';
else if (p.exported_at !== bundle.exported_at) manifestError = 'manifest exported_at mismatch';
else if (entries.length !== expectedEntries.length) manifestError = `manifest entries count (${entries.length}) does not match exported records (${expectedEntries.length})`;
else if (!entries.every((e, idx) => refsEqual(e, expectedEntries[idx]))) manifestError = 'manifest entries do not exactly enumerate the exported records in order';
else if (p.snapshot_count !== snapshots.length) manifestError = `manifest snapshot_count (${p.snapshot_count}) does not match (${snapshots.length})`;
else if (p.journal_count !== journal.length) manifestError = `manifest journal_count (${p.journal_count}) does not match (${journal.length})`;
else if (p.history_head_digest !== historyHead) manifestError = 'manifest history_head_digest mismatch';
else if (p.sequence !== undefined && (!isInteger(p.sequence) || p.sequence < 1)) manifestError = 'manifest sequence is not a positive integer';
if (manifestError) {
results.valid = false;
results.manifestValid = false;
results.chainFailed++;
results.errors.push(`[chain] Manifest: ${manifestError}`);
}
results.sequence = p.sequence ?? 1;
results.chainChecks++;
if (isString(opts.historyHead)) {
results.historyHeadPinned = opts.historyHead.toLowerCase() === String(p.history_head_digest).toLowerCase();
if (!results.historyHeadPinned) {
results.valid = false;
results.chainFailed++;
results.errors.push('[chain] current history head does not match --history-head');
}
}
const manifests = [...priorManifests, bundle.manifest];
let historyChainError = null;
if (priorManifests.length > 0 || p.sequence !== undefined) {
const retained = new Set(expectedEntries.map((entry) => entry.digest));
for (let i = 0; i < manifests.length && !historyChainError; i++) {
const current = manifests[i];
const payload = current?.payload;
const expectedSequence = i + 1;
if ((payload?.sequence ?? expectedSequence) !== expectedSequence) {
historyChainError = `manifest sequence mismatch at ${expectedSequence}`;
break;
}
if (i > 0) {
const previous = manifests[i - 1];
if (payload?.previous_manifest_digest !== previous?.digest
|| payload?.previous_history_head_digest !== previous?.payload?.history_head_digest) {
historyChainError = `manifest previous-head mismatch at sequence ${expectedSequence}`;
break;
}
}
for (const entry of (isArray(payload?.entries) ? payload.entries : [])) {
if (!retained.has(entry.digest)) {
historyChainError = `current export omits prior record ${entry.digest}`;
break;
}
}
}
results.historyChainValid = historyChainError === null;
results.chainChecks++;
if (historyChainError) {
results.valid = false;
results.chainFailed++;
results.errors.push(`[chain] History: ${historyChainError}`);
}
}
if (anchors.length > 0) {
results.historyAnchored = true;
const offset = manifests.length - anchors.length;
let anchorError = null;
for (let i = 0; i < anchors.length && !anchorError; i++) {
const anchor = anchors[i];
const anchorPayload = anchor?.payload;
const manifest = manifests[offset + i];
if (!manifest) {
anchorError = `anchor ${i + 1} has no corresponding manifest`;
break;
}
const previousAnchor = i > 0 ? anchors[i - 1]?.digest : null;
if (anchorPayload?.schema !== MACRO_ANCHOR_SCHEMA
|| anchorPayload?.sequence !== manifest.payload?.sequence
|| anchorPayload?.manifest_digest !== manifest.digest
|| anchorPayload?.history_head_digest !== manifest.payload?.history_head_digest
|| anchorPayload?.previous_anchor_digest !== previousAnchor) {
anchorError = `anchor mismatch at sequence ${anchorPayload?.sequence ?? i + 1}`;
}
}
results.chainChecks++;
if (anchorError) {
results.valid = false;
results.chainFailed++;
results.errors.push(`[chain] Anchor: ${anchorError}`);
}
const anchorHead = anchors.at(-1)?.digest;
if (isString(opts.anchorHead)) {
results.anchorHeadPinned = opts.anchorHead.toLowerCase() === String(anchorHead).toLowerCase();
results.chainChecks++;
if (!results.anchorHeadPinned) {
results.valid = false;
results.chainFailed++;
results.errors.push('[chain] current anchor head does not match --anchor-head');
}
}
}
} else {
// Manifest signature failed; inventory cannot be trusted.
results.chainChecks++;
results.chainFailed++;
results.valid = false;
results.errors.push('[chain] Manifest signature invalid; inventory cannot be verified');
}
// Optional RFC 6962 transparency evidence: confirm every exported record
// digest is committed under a signed (and optionally witnessed) log head.
// A bundle WITHOUT a transparency field stays valid (backward compatible).
if (isObject(bundle.transparency)) {
const recordDigests = [...snapshots, ...journal]
.map((t) => (isString(t?.digest) ? t.digest : null))
.filter(Boolean);
const transparency = verifyTransparencyEvidence(bundle.transparency, recordDigests);
results.transparencyAnchor = transparency;
results.chainChecks++;
if (!transparency.head_valid || !transparency.all_included) {
results.valid = false;
results.chainFailed++;
const why = !transparency.head_valid
? 'transparency head is not a valid signed log head'
: 'one or more exported records are not provably included in the signed log';
results.errors.push(`[chain] Transparency: ${why}${transparency.errors.length ? ` (${transparency.errors[0]})` : ''}`);
}
}
results.signers = [...signerRoles.entries()].map(([key, roles]) => ({ key, roles: [...roles].sort(), isModelKey: key === modelKey }));
if (!results.valid) results.error = firstError || 'chain_link_mismatch';
return results;
}
/**
* Trusted Context Pack verifier (TCB v1).
*
* A fund's desktop runtime turns an approved file (a positions export, a blotter,
* a mandate, a research folder) into a SIGNED TrustedContextPack before any agent
* or gate operates over it. This engine lets a third party (an allocator, an LP,
* an auditor) re-verify that pack offline, holding only this open tool and no
* ScopeBlind code: the digest is recomputed over the canonical payload and the
* Ed25519 signature is checked over that digest against the embedded (or pinned)
* key, exactly like a Gate receipt tuple.
*
* The TCB-specific check is the relabel guard: gate_status MUST equal the status
* derived from the signed confidence and freshness. A pack cannot be re-signed to
* claim a low-confidence or stale parse is `usable`. This is what makes the
* confidence-gating trustworthy to someone who did not produce the pack.
*
* What a verified pack proves: these exact bytes, with this file hash, parsed to
* this context at this confidence and freshness, signed by this key. What it does
* NOT prove: that the source file is authentic, complete, or the fund's true book.
* That requires a custodian-signed feed or a DKIM/PAdES source (a stronger tier).
*
* @module verify-cli/src/engines/trusted-context-pack
* @license Apache-2.0
*/
import { ed25519 } from '@noble/curves/ed25519';
import { sha256 } from '@noble/hashes/sha256';
import { utf8ToBytes } from '@noble/hashes/utils';
import { sortKeysDeep } from '../util/canonical.js';
import { hexToBytes, bytesToHex } from '../util/hex.js';
export const TCB_SCHEMA = 'scopeblind.trusted_context_pack.v1';
const TCB_USABLE_THRESHOLD = 0.75;
const HEX_64 = /^[0-9a-f]{64}$/;
const SOURCE_TYPES = new Set(['book_positions', 'nav_account', 'blotter', 'risk_report', 'mandate_limits', 'research', 'operations', 'unknown']);
const GATE_STATUSES = new Set(['usable', 'needs_approval', 'blocked']);
const isObject = (v) => v !== null && typeof v === 'object' && !Array.isArray(v);
const isString = (v) => typeof v === 'string' && v.length > 0;
const isNumber = (v) => typeof v === 'number' && Number.isFinite(v);
export function canonicalTcbJSON(payload) {
return JSON.stringify(sortKeysDeep(payload));
}
/** The single source of truth for the gate decision (kept in sync with
* scopeblind-pm/src/trusted-context.ts:gateStatusFor). */
export function gateStatusFor(confidence, freshness) {
if (confidence <= 0) return 'blocked';
if (confidence < TCB_USABLE_THRESHOLD || freshness?.stale === true) return 'needs_approval';
return 'usable';
}
export const TCB_PROVES = [
'Authenticity: the pack was signed by the Ed25519 key it carries (the fund runtime that built it).',
'Integrity: the file hash, parsed context, confidence, freshness, and gate decision are bound by the signature and unmodified.',
'Honest gating: gate_status matches the confidence and freshness, so a low-confidence or stale parse cannot be relabeled usable.',
];
export const TCB_LIMITATIONS = [
'That the source file is authentic, complete, or the fund\'s true book; a pack attests the parse, not the provenance.',
'Correctness of the original file behind file_hash unless its bytes are separately disclosed and re-hashed.',
'Whether the embedded verification_key is the runtime you expect; pin it with --key to bind trust to a known signer.',
'A stronger source tier (custodian-signed feed, DKIM or PAdES) is needed to attest where the data came from.',
];
function collectFields(payload) {
const out = {};
for (const k of ['source_type', 'source_format', 'source_lineage', 'file_name', 'file_hash', 'parser_version', 'confidence', 'gate_status', 'workspace_id', 'source_id']) {
if (payload[k] !== undefined && payload[k] !== null) out[k] = payload[k];
}
if (isObject(payload.freshness)) out.freshness = { as_of: payload.freshness.as_of ?? null, stale: payload.freshness.stale === true };
if (Array.isArray(payload.warnings)) out.warnings = payload.warnings;
if (isObject(payload.summary)) out.summary = payload.summary;
return out;
}
function schemaErrors(payload) {
const errors = [];
for (const f of ['workspace_id', 'source_id', 'source_format', 'file_hash', 'parser_version']) {
if (!isString(payload[f])) errors.push(`missing or empty ${f}`);
}
if (!SOURCE_TYPES.has(payload.source_type)) errors.push(`invalid source_type ${JSON.stringify(payload.source_type)}`);
if (!GATE_STATUSES.has(payload.gate_status)) errors.push(`invalid gate_status ${JSON.stringify(payload.gate_status)}`);
if (!HEX_64.test(payload.file_hash || '')) errors.push('file_hash must be 64 lowercase hex characters');
if (!isNumber(payload.confidence) || payload.confidence < 0 || payload.confidence > 1) errors.push('confidence must be a number in [0,1]');
if (!Array.isArray(payload.warnings)) errors.push('warnings must be an array');
if (!isObject(payload.parsed_artifacts)) errors.push('parsed_artifacts must be an object');
if (!isObject(payload.freshness) || !isString(payload.freshness.ingested_at)) errors.push('freshness.ingested_at is required');
else if (typeof payload.freshness.stale !== 'boolean') errors.push('freshness.stale must be a boolean');
// The relabel guard: gate_status must follow from the signed confidence/freshness.
if (errors.length === 0) {
const expected = gateStatusFor(payload.confidence, payload.freshness);
if (payload.gate_status !== expected) errors.push(`gate_status ${JSON.stringify(payload.gate_status)} does not match the signed confidence and freshness (expected ${expected})`);
}
return errors;
}
/**
* Verify a TrustedContextPack tuple { payload, digest, signature, verification_key }.
*
* @param {object} tuple
* @param {{ publicKey?: string }} [opts]
*/
export function verifyTrustedContextPack(tuple, opts = {}) {
const base = { format: 'trusted-context-pack', schema: null, schemaRecognized: false, algorithm: 'ed25519' };
if (!isObject(tuple)) return { valid: false, error: 'unknown_format', ...base, detail: 'pack is not an object' };
const payload = tuple.payload;
if (!isObject(payload)) return { valid: false, error: 'missing_payload', ...base };
const schema = isString(payload.schema) ? payload.schema : null;
base.schema = schema;
base.schemaRecognized = schema === TCB_SCHEMA;
base.payloadFields = collectFields(payload);
if (schema !== TCB_SCHEMA) return { valid: false, error: 'unknown_format', ...base, detail: `expected schema ${TCB_SCHEMA}` };
if (!isString(tuple.signature)) return { valid: false, error: 'missing_signature', ...base };
if (!isString(tuple.digest) || !HEX_64.test(tuple.digest)) return { valid: false, error: 'malformed_hex', ...base, detail: 'digest must be 64 lowercase hex characters' };
if (!isString(tuple.verification_key)) return { valid: false, error: 'no_public_key', ...base };
const pinned = isString(opts.publicKey);
if (pinned && opts.publicKey.toLowerCase() !== tuple.verification_key.toLowerCase()) {
return { valid: false, error: 'key_mismatch', ...base, publicKey: tuple.verification_key, expectedKey: opts.publicKey };
}
const recomputed = bytesToHex(sha256(utf8ToBytes(canonicalTcbJSON(payload))));
if (recomputed !== tuple.digest) return { valid: false, error: 'digest_mismatch', ...base, digest: tuple.digest, recomputedDigest: recomputed, publicKey: tuple.verification_key };
let ok = false;
try {
ok = ed25519.verify(hexToBytes(tuple.signature), hexToBytes(tuple.digest), hexToBytes(tuple.verification_key));
} catch (e) {
return { valid: false, error: 'malformed_hex', ...base, digest: tuple.digest, detail: e.message, publicKey: tuple.verification_key };
}
if (!ok) return { valid: false, error: 'invalid_signature', ...base, digest: tuple.digest, publicKey: tuple.verification_key };
const semanticErrors = schemaErrors(payload);
if (semanticErrors.length) return { valid: false, error: 'schema_invalid', ...base, digest: tuple.digest, publicKey: tuple.verification_key, detail: semanticErrors.join('; '), semanticErrors };
return {
valid: true,
...base,
digest: tuple.digest,
publicKey: tuple.verification_key,
keySource: pinned ? 'embedded-tuple (pinned via --key)' : 'embedded-tuple',
gateStatus: payload.gate_status,
confidence: payload.confidence,
sourceType: payload.source_type,
proves: TCB_PROVES,
limitations: TCB_LIMITATIONS,
};
}
/**
* Known-issuer labels.
*
* Verifying a signature proves the bytes were signed by a given key, not WHO holds
* it (the engines say this in their limitations). A known-issuers map turns a raw
* hex key into a human label in the output ("Signer: Meridian Global Macro Desk")
* so a reader who has pinned trust to a known desk sees the name, not just hex. It
* is a display aid layered on top of `--key` pinning, never a trust shortcut: an
* unlabeled key still verifies, and a labeled key is only as trustworthy as the map
* the verifier chose to load.
*
* @module verify-cli/src/util/known-issuers
* @license Apache-2.0
*/
import { readFileSync } from 'node:fs';
/**
* Load and merge issuer label maps (hex public key -> label). A bundled default is
* overlaid with an optional user file (the user file wins). Keys are normalized to
* lowercase hex. Unreadable or malformed files are ignored (labels are non-critical).
*
* @param {string|undefined} userPath path passed via --known-issuers
* @param {string|undefined} bundledPath path to the package's known-issuers.json
* @returns {Record<string,string>} lowercase-hex key -> label
*/
export function loadKnownIssuers(userPath, bundledPath) {
const merged = {};
for (const p of [bundledPath, userPath]) {
if (!p) continue;
try {
const obj = JSON.parse(readFileSync(p, 'utf8'));
if (obj && typeof obj === 'object') {
for (const [k, v] of Object.entries(obj)) {
if (k.startsWith('_')) continue; // _comment / _note keys are documentation
if (typeof v === 'string' && /^[0-9a-fA-F]+$/.test(k)) merged[k.toLowerCase()] = v;
}
}
} catch { /* labels are non-critical; ignore unreadable/malformed files */ }
}
return merged;
}
/** Resolve a label for a hex key, or null. Case-insensitive. */
export function labelFor(key, issuers) {
if (typeof key !== 'string' || !issuers) return null;
return issuers[key.toLowerCase()] || null;
}
+99
-22
# Changelog
## Unreleased
## 0.9.3 (2026-07-08)
### Restraint receipts: prove what was prevented, offline and position-blind
### Tree reconciliation: the 0.9.1/0.9.2 line and this line are one again
A restraint receipt (`tool: gate.restrain`) is already verified as a Legate
governed receipt. This release re-verifies and surfaces its openable detail, so
the receipt proves not merely that a deny was signed but exactly WHAT was
prevented and WHY:
npm 0.9.1/0.9.2 were published from a tree that had diverged from this one.
This release unifies them: everything published there now lives here
(restraint-receipt openable detail with re-hashed bindings and the
`Prevented:` terminal block, `verifyRestraintBindings` export, the RFC 9711
EAT output modes `--emit-eat` / `--emit-eat-cbor`, the `verify` bin alias,
`samples/sample-restraint-receipt.json`), and everything that had only
lived here ships to npm for the first time (Legate proof-pack, macro
snapshot and track-record, and trusted-context-pack engines).
- The disclosed denial outcome (the determining rules, risk band, mandate
digest) is re-hashed and confirmed to bind to the signed `result_sha256`, and
the proposed blocked order is re-hashed under its salt and confirmed to bind to
`input_sha256`. Re-hashing uses the same JCS canonicalization the runtime used,
so altering the disclosed detail flips the binding to a failure while the
signature stays valid over the original hashes (you cannot lie about what was
blocked).
- Position-blind by construction: the blocked order can be withheld, and the
outcome still verifies because the order is salt-committed into the signed input
hash and openable to a regulator on demand.
- Terminal output gains a `Prevented:` block (risk band, determining rules, the
blocked order or a position-blind note, and the two binding checks). New
`verifyRestraintBindings` export. A sample lives at
`samples/sample-restraint-receipt.json`; see `RESTRAINT-DEMO.md`.
- Added a `verify` bin alias (alongside `verify-artifact`) so
`npx @veritasacta/verify <receipt>` reads naturally.
### draft-02 receipts and s5.7 chain links
protect-mcp 0.10.0 emits draft-farley-acta-signed-receipts-02 envelopes;
these verified here already via the passport path. `--replay-chain` now
recomputes chain links under both conventions: the draft-02 section 5.7
hash (SHA-256 over the JCS bytes of the entire previous envelope, signature
included) and the older payload-only hash, so a mixed pre/post-migration
receipt log replays cleanly including the link that spans the boundary.
### s5.7 chain links in --replay-chain
`--replay-chain` now recomputes chain links under both conventions: the
draft-farley-acta-signed-receipts-02 section 5.7 hash (SHA-256 over the JCS
bytes of the entire previous envelope, signature included), which is what
protect-mcp 0.10.0+ writes, and the older payload-only hash for chains
written before the migration. A mixed pre/post-migration receipt log
replays cleanly, including the link that spans the boundary.
Tree reconciliation blocker: RESOLVED in this release (see above).
## 0.9.0 (2026-06-22)
### Legate adherence / restraint proof packs
Recognizes and verifies `scopeblind.legate.proof-pack.v1`: the allocator-facing,
position-blind record a Legate desk produces of what the gate prevented over a
session (held / blocked, attributed to the committed-mandate rules) plus order-path
shadow evidence (what it would have blocked on a FIX feed), bound to the mandate
digest, the signed book provenance, and a receipt Merkle root. The signature is
Ed25519 over the canonical (deep-sorted, no-whitespace) bytes of the pack minus its
`signature`, `sha256`, and `hybrid_signature` fields, against the embedded runtime
`verification_key` (pin it with `--key`). Cross-implementation tested against a real
desktop-runtime-signed fixture (`samples/legate-proof-pack.json`); tampering with any
field, and a wrong pinned key, fail. An optional `hybrid_signature` (Ed25519 +
ML-DSA-65) is recognized and reported; classical Ed25519 is verified here, with PQ
verification documented as an optional add-on in the restraint-receipts draft.
## 0.8.0 (2026-06-13)
### RFC 6962 transparency log for macro track records
Recognizes `scopeblind.macro.transparency-head/1` and
`scopeblind.macro.transparency-witness/1`, and verifies the `transparency`
evidence carried in a macro track-record bundle: every record's Merkle
inclusion proof against the signed head (RFC 6962 hashing: leaf =
sha256(0x00||digest), node = sha256(0x01||l||r)), plus an independent witness
co-signature. The bundle result reports `Transparency: witness-anchored /
self-signed / not anchored`; a tampered head or a missing inclusion fails the
chain check. No new signing crypto — inclusion is recomputed from the path and
checked against the head root. This is what makes a dropped or rewritten record
detectable to anyone who retained a head, not merely a single un-trimmed export.
### ScopeBlind macro-engine snapshots and track-record bundles
New engine `src/engines/macro-snapshot.js` recognizes the macro-engine
schemas (`scopeblind.macro.market-state/1`, `regime-snapshot/1`,
`tape-snapshot/1`, `vulnerability/1`, `alert/1`, `journal-entry/1`) and the
signed track-record bundle (`scopeblind.macro.track-record-bundle/1`). Macro
snapshots already verified cryptographically as generic Gate tuples; this adds
schema recognition, a per-schema semantic-contract check, and a schema-aware
summary in the output (no more "unrecognized schema" for macro records). No
new cryptography: crypto is delegated to `verifyGateTuple` and canonicalization
to `canonicalGateJSON`.
The track-record bundle verifier mirrors the Gate evidence-bundle: it checks
every record's signature, single-signer custody (every record including the
manifest shares one model key), exact manifest completeness (entries enumerate
the snapshots then journal entries in order), the snapshot/journal counts, and
the `history_head_digest` over the ordered record digests. Dropping or
tampering any record breaks the bundle. `--mode macro` forces the bundle path.
Anchored exports additionally carry a monotonic manifest sequence, previous
manifest/history-head links, retained prior manifests, and a signed checkpoint
chain. Verification rejects deletion of any previously manifested record.
`--key` is now reported explicitly as the operator-identity trust boundary;
without it the result proves embedded-key integrity only. `--history-head` and
`--anchor-head` pin independently retained anti-rollback checkpoints.
## 0.7.0 (2026-06-12)
### Release rule for execution evidence
Bundles whose entries carry fills under an unreleased decision fail the
chain check: fills require an ALLOW parent, or an APPROVAL_REQUIRED
parent with a present approval whose decision is approved. A DENY or
REVIEW parent with fills always fails. Without this rule a bundle could
present individually valid signatures as evidence of an unauthorized
execution.
### ScopeBlind Gate receipt tuples and evidence bundles

@@ -30,0 +107,0 @@

+45
-3

@@ -47,3 +47,6 @@ #!/usr/bin/env node

import { verifyGateTuple, verifyGateBundle } from './src/engines/gate-receipt.js';
import { verifyMacroTrackRecord } from './src/engines/macro-snapshot.js';
import { verifyLegateGovernedReceipt } from './src/engines/legate-governed-receipt.js';
import { verifyLegateProofPack } from './src/engines/legate-proof-pack.js';
import { verifyTrustedContextPack } from './src/engines/trusted-context-pack.js';
import { verifyVoprfToken } from './src/engines/voprf-token.js';

@@ -78,2 +81,3 @@ import { verifyKnowledgeUnit } from './src/engines/knowledge-unit.js';

import { resolveFromJwks } from './src/util/jwks.js';
import { loadKnownIssuers, labelFor } from './src/util/known-issuers.js';
import { appendAuditEntry } from './src/util/audit-log.js';

@@ -89,3 +93,5 @@ import { fipsStatus } from './src/util/fips.js';

formatGateBundleResult,
formatMacroTrackRecordResult,
formatGovernedReceiptResult,
formatTrustedContextPackResult,
formatKuResult,

@@ -115,3 +121,6 @@ formatSelfCheckResult,

'gate-evidence-bundle': 'ScopeBlind Gate evidence bundle (receipt tuples + chain links)',
'macro-track-record': 'ScopeBlind macro-engine track-record bundle (signed snapshots + completeness manifest)',
'legate-governed-receipt': 'Legate governed receipt (Ed25519 over canonical action payload)',
'legate-proof-pack': 'Legate adherence / restraint proof pack (Ed25519 over canonical bytes, position-blind)',
'trusted-context-pack': 'ScopeBlind Trusted Context Pack (signed parsed-context attestation)',
};

@@ -153,2 +162,3 @@

replayChain: null,
emitEat: null,
diff: null,

@@ -158,3 +168,2 @@ auditReport: false,

emitVerificationReceipt: false,
emitEat: null,
fips: false,

@@ -167,2 +176,4 @@ subcommand: null,

frameworkOverride: null,
historyHead: null,
anchorHead: null,
};

@@ -180,4 +191,7 @@

case '-k': opts.publicKey = next(); break;
case '--known-issuers': opts.knownIssuers = next(); break;
case '--jwks': opts.jwksUrl = next(); break;
case '--trust-anchor': opts.trustAnchor = next(); break;
case '--history-head': opts.historyHead = next(); break;
case '--anchor-head': opts.anchorHead = next(); break;
case '--stdin': opts.stdin = true; break;

@@ -205,2 +219,4 @@ case '--mode': opts.mode = next(); break;

case '--replay-chain': opts.replayChain = next(); break;
case '--emit-eat': opts.emitEat = 'json'; break;
case '--emit-eat-cbor': opts.emitEat = 'cbor'; break;
case '--diff': opts.diff = next(); break;

@@ -210,4 +226,2 @@ case '--audit-report': opts.auditReport = true; break;

case '--emit-verification-receipt': opts.emitVerificationReceipt = true; break;
case '--emit-eat': opts.emitEat = 'json'; break;
case '--emit-eat-cbor': opts.emitEat = 'cbor'; break;
case '--fips': opts.fips = true; break;

@@ -306,2 +320,4 @@ case '--allow-partial-voprf': opts.allowPartialVoprf = true; break;

--trust-anchor <file> Local trust-anchor JSON with public keys
--history-head <hex> Pin the expected macro track-record history head
--anchor-head <hex> Pin the expected signed macro anchor digest
--mode <m> Force mode: receipt|voprf|ku|auto (default: auto)

@@ -331,2 +347,4 @@ --bundle Verify as audit bundle

--replay-chain <file> Verify every receipt in a JSONL chain file
--emit-eat Re-emit the verified receipt as an RFC 9711 EAT claims-set (JSON)
--emit-eat-cbor Same, as CBOR with integer claim keys
--diff <other-file> Show structural diff between two receipts

@@ -511,3 +529,5 @@

else if (forced === 'gate-bundle') detected.mode = 'gate-evidence-bundle';
else if (forced === 'macro' || forced === 'macro-track-record') detected.mode = 'macro-track-record';
else if (forced === 'governed') detected.mode = 'legate-governed-receipt';
else if (forced === 'context' || forced === 'context-pack') detected.mode = 'trusted-context-pack';
}

@@ -547,2 +567,6 @@ if (opts.bundle) detected.mode = 'ed25519-bundle';

}
case 'macro-track-record': {
const r = verifyMacroTrackRecord(input, subOpts);
return { ...r, modeLabel: MODE_LABELS['macro-track-record'] };
}
case 'gate-receipt-tuple': {

@@ -556,2 +580,10 @@ const r = verifyGateTuple(input, subOpts);

}
case 'legate-proof-pack': {
const r = verifyLegateProofPack(input, subOpts);
return { ...r, modeLabel: MODE_LABELS['legate-proof-pack'] };
}
case 'trusted-context-pack': {
const r = verifyTrustedContextPack(input, subOpts);
return { ...r, modeLabel: MODE_LABELS['trusted-context-pack'] };
}
case 'knowledge-unit': {

@@ -1236,2 +1268,10 @@ const r = await verifyKnowledgeUnit(input, subOpts);

// Resolve a human label for the signer key, if one is known. Display aid only;
// it never changes the verification result.
if (result && typeof result === 'object' && typeof result.publicKey === 'string') {
const issuers = loadKnownIssuers(opts.knownIssuers, join(__dirname, 'known-issuers.json'));
const label = labelFor(result.publicKey, issuers);
if (label) result.signerLabel = label;
}
// Output

@@ -1258,4 +1298,6 @@ if (opts.json) {

else if (result.format === 'gate-evidence-bundle') console.log(formatGateBundleResult(result, opts));
else if (result.format === 'macro-track-record') console.log(formatMacroTrackRecordResult(result, opts));
else if (result.format === 'gate-tuple') console.log(formatGateTupleResult(result, opts));
else if (result.format === 'legate-governed-receipt') console.log(formatGovernedReceiptResult(result, opts));
else if (result.format === 'trusted-context-pack') console.log(formatTrustedContextPackResult(result, opts));
else if (result.total !== undefined) console.log(formatBundleResult(result, opts));

@@ -1262,0 +1304,0 @@ else console.log(formatReceiptResult(result, opts));

+6
-9
{
"name": "@veritasacta/verify",
"version": "0.9.2",
"version": "0.9.3",
"mcpName": "io.github.tomjwxf/veritasacta-verify",
"description": "Unified offline verifier for signed decision receipts, Legate proof packs, VOPRF anonymous credentials, and selective-disclosure receipts. Ed25519 + ML-DSA-65 hybrid. IETF draft-farley-acta-signed-receipts. scopeblind.com",
"description": "Offline verifier for Veritas Acta signed receipts. Powers protect-mcp, ScopeBlind cold-chain hardware, and Microsoft AGT Lesson 18.",
"license": "Apache-2.0",

@@ -22,8 +22,5 @@ "type": "module",

"ROADMAP.md",
"samples/sample-bundle.json",
"samples/sample-gate-bundle.json",
"samples/sample-gate-tuple.json",
"samples/sample-receipt.json",
"samples/sample-restraint-receipt.json",
"test/conformance.js"
"samples/",
"test/conformance.js",
"known-issuers.json"
],

@@ -56,3 +53,3 @@ "dependencies": {

"scripts": {
"test": "node --test 'test/unit/**/*.test.js' 'test/integration/**/*.test.js'",
"test": "node --test test/unit/*.test.js test/integration/*.test.js",
"test:conformance": "node test/conformance.js",

@@ -59,0 +56,0 @@ "self-test": "node cli.js --self-test",

@@ -41,4 +41,3 @@ # @veritasacta/verify

| Gate receipt / bundle | ScopeBlind Gate receipt tuples (`scopeblind.gate.*`) and signed-manifest `scopeblind.gate.evidence-bundle/2` exports with semantic and exact chain checks | T1 |
| Legate governed receipt | Desktop runtime receipts (`scopeblind.legate.governed.*`) with determining-rule attribution and mandate-digest binding | T1 |
| Legate proof pack | Position-blind adherence records (`scopeblind.legate.proof-pack.v1`): held/blocked by rule, order-path shadow evidence, bound to mandate digest + signed-book provenance + receipt Merkle root. Ed25519 + optional hybrid ML-DSA-65 | T1 |
| Macro track record | Signed macro snapshots, append-only manifest sequence, and signed history checkpoints | T1 |

@@ -103,2 +102,20 @@ ## Subcommands

### ScopeBlind macro track records
Macro exports verify offline. An embedded key proves internal signature
integrity, not who controls that key. Pin the operator key and an independently
retained anti-rollback head for identity and historical assurance:
```bash
npx @veritasacta/verify@0.8.0 legate-macro-track-record.json \
--key <operator-ed25519-public-key> \
--history-head <expected-history-head> \
--anchor-head <expected-anchor-digest>
```
The verifier checks every record, the exact current manifest inventory, prior
manifest links, retention of previously manifested records, and the signed
checkpoint chain. Publication at a mutable URL is not itself a transparency
log; retain or independently timestamp checkpoint heads.
### Pre-built sandbox profiles

@@ -114,3 +131,3 @@

- **Self-verifying.** `--self-check` cryptographically proves the installed verifier (24 source files) matches the canonical release.
- **Algorithm-agile.** Hybrid PQ (`ed25519+ml-dsa-65`) recognized and verified (v0.9+).
- **Algorithm-agile.** Hybrid PQ (`ed25519+ml-dsa-65`) recognized; full PQ in v0.6+.
- **Zero telemetry.** The verifier never phones home.

@@ -117,0 +134,0 @@

{
"sigil_version": 1,
"fingerprint": "677a8a81",
"name": "Open Wind",
"sigil_hash": "677a8a812c7a9d896bee2d7f8dfde02d347ac742fa4cd8830c9e292e92b9e676",
"fingerprint": "b309bd8b",
"name": "Woven Meadow",
"sigil_hash": "b309bd8b8644efcc07e737cff69cb7a87eaa9c8c9d728baf751c89b882c2c1cd",
"project_public_key": "fe665e861867cec7e171c0c13bbc873c3362079faef21f54df7804b7fb9ae8af",

@@ -10,4 +10,4 @@ "policy": {

"package": "@veritasacta/verify",
"package_version": "0.5.4",
"source_hash": "4eca3a4aa71e50cf983285520ff8ec93e2ece12d2912f0b7b60b5c7034b879f9",
"package_version": "0.7.0",
"source_hash": "ab926d490a512418c8028cd46eb766a100602e28b9c5f26381585030763a2fab",
"monitored_files": [

@@ -19,2 +19,3 @@ "cli.js",

"src/engines/ed25519-receipt.js",
"src/engines/gate-receipt.js",
"src/engines/voprf-token.js",

@@ -61,6 +62,6 @@ "src/engines/knowledge-unit.js",

],
"created_at": 1776673390228
"created_at": 1781269520160
},
"policy_hash": "3d9bbcbea4af4032c7e77fc1f0a8606553e9a53bf8df0f09ed0bcd0859faa92a",
"derived_at": "2026-04-20T08:23:10.228Z"
"policy_hash": "7d517dbbb5824d09186ec8b2344febeb5e62e5dc54bcb191c59da13f2ee03b9a",
"derived_at": "2026-06-12T13:05:20.160Z"
}

@@ -14,2 +14,3 @@ /**

* - 'gate-evidence-bundle' — ScopeBlind Gate evidence bundle (scopeblind.gate.evidence-bundle/2)
* - 'macro-track-record' — ScopeBlind macro-engine track-record bundle (scopeblind.macro.track-record-bundle/1)
* - 'unknown'

@@ -79,2 +80,29 @@ *

// ScopeBlind macro-engine track-record bundle: explicit schema marker +
// snapshots[] + a signed manifest tuple.
if (
input.schema === 'scopeblind.macro.track-record-bundle/1'
&& Array.isArray(input.snapshots)
&& input.manifest && typeof input.manifest === 'object' && !Array.isArray(input.manifest)
) {
signals.push(`schema=${input.schema}`, 'snapshots[]', 'manifest');
return { mode: 'macro-track-record', signals, hasSelectiveDisclosure: false, isBundle: true };
}
// ScopeBlind Trusted Context Pack: a Gate-tuple-shaped envelope whose payload
// carries the TCB schema marker. Detected BEFORE the generic gate tuple (it
// matches that shape too) and routed to engines/trusted-context-pack.js so a
// third party re-verifies the parsed-context attestation, its confidence, and
// its gate decision offline.
if (
input.payload && typeof input.payload === 'object' && !Array.isArray(input.payload)
&& input.payload.schema === 'scopeblind.trusted_context_pack.v1'
&& typeof input.digest === 'string'
&& typeof input.signature === 'string'
&& typeof input.verification_key === 'string'
) {
signals.push('schema=scopeblind.trusted_context_pack.v1');
return { mode: 'trusted-context-pack', signals, hasSelectiveDisclosure: false, isBundle: false };
}
// ScopeBlind Gate receipt tuple: { payload, digest, signature, verification_key }.

@@ -94,2 +122,17 @@ // The flat hex signature string distinguishes it from the Passport

// Legate adherence / restraint proof pack: type scopeblind.legate.proof-pack.v1,
// signed by the runtime key (verification_key) over the canonical bytes of the pack
// minus signature/sha256. A position-blind record of what the gate prevented (held /
// blocked, by rule) plus order-path shadow evidence. Detected before the v1-flat
// catch-all so it routes to engines/legate-proof-pack.js. Routed by its type.
if (
input.type === 'scopeblind.legate.proof-pack.v1'
&& typeof input.signature === 'string'
&& (typeof input.verification_key === 'string'
|| (input.runtime && typeof input.runtime.verification_key === 'string'))
) {
signals.push('type=scopeblind.legate.proof-pack.v1', 'signature+verification_key');
return { mode: 'legate-proof-pack', signals, hasSelectiveDisclosure: false, isBundle: false };
}
// Legate governed receipt: a FLAT, pipe-delimited canonical payload

@@ -96,0 +139,0 @@ // scopeblind.receipt.v1|<id>|<tool>|<decision>|<input_sha256>|<result_sha256>|<at>

@@ -46,2 +46,6 @@ /**

let previousPayloadHash = null;
// draft-farley-acta-signed-receipts-02 s5.7: the chain hash covers the
// ENTIRE previous envelope, signature included. Kept alongside the older
// payload-only convention so chains spanning the migration verify.
let previousEnvelopeHash = null;

@@ -63,11 +67,14 @@ for (let i = 0; i < lines.length; i++) {

if (expectedPrev !== undefined && expectedPrev !== null && previousPayloadHash !== null) {
if (expectedPrev !== undefined && expectedPrev !== null
&& (previousPayloadHash !== null || previousEnvelopeHash !== null)) {
const expectedPrevHex = expectedPrev.startsWith('sha256:')
? expectedPrev.slice(7)
: expectedPrev;
if (expectedPrevHex !== previousPayloadHash) {
// s5.7 full-envelope hash is the current convention; the payload-only
// hash is accepted for chains written before the draft-02 migration.
if (expectedPrevHex !== previousEnvelopeHash && expectedPrevHex !== previousPayloadHash) {
results.failed++;
results.chainBreaks++;
results.errors.push(
`Line ${i + 1}: chain_break (expected prev sha256:${previousPayloadHash.slice(0, 16)}..., got ${expectedPrev.slice(0, 24)}...)`,
`Line ${i + 1}: chain_break (expected prev ${String(previousEnvelopeHash).slice(0, 16)}... (s5.7) or ${String(previousPayloadHash).slice(0, 16)}... (payload-only), got ${expectedPrev.slice(0, 24)}...)`,
);

@@ -100,4 +107,11 @@ results.valid = false;

// Compute the canonical hash of this receipt's payload for the next chain check
// Compute both chain-link candidates for the next check: the s5.7 hash of
// the entire receipt as written (signature included), and the older
// payload-only hash.
try {
previousEnvelopeHash = createHash('sha256').update(canonicalize(receipt), 'utf-8').digest('hex');
} catch {
previousEnvelopeHash = null;
}
try {
const canonicalStr = canonicalize(payload);

@@ -104,0 +118,0 @@ previousPayloadHash = createHash('sha256').update(canonicalStr, 'utf-8').digest('hex');

@@ -7,2 +7,3 @@ /** ScopeBlind Gate receipt and evidence-bundle verifier. */

import { hexToBytes, bytesToHex } from '../util/hex.js';
import { isMacroSchema, macroSchemaErrors, macroSummary, MACRO_PROVES, MACRO_LIMITATIONS } from './macro-snapshot.js';

@@ -19,2 +20,4 @@ export const GATE_BUNDLE_SCHEMA = 'scopeblind.gate.evidence-bundle/2';

'scopeblind.gate.evidence-manifest/1': 'signed bundle manifest',
'scopeblind.gate.reconciliation/1': 'custodian-statement reconciliation',
'scopeblind.gate.stress/1': 'regime stress-test result',
'scopeblind.mandate.delegation/1': 'issuer-signed mandate delegation',

@@ -138,4 +141,6 @@ };

const schema = isString(payload.schema) ? payload.schema : null;
const schemaRecognized = schema !== null && Object.hasOwn(GATE_SCHEMAS, schema);
Object.assign(base, { schema, schemaRecognized, type: schema || undefined, payloadFields: collectGatePayloadFields(payload), chainFields: collectGateChainFields(payload) });
const macro = schema !== null && isMacroSchema(schema);
const schemaRecognized = schema !== null && (Object.hasOwn(GATE_SCHEMAS, schema) || macro);
Object.assign(base, { schema, schemaRecognized, macroSchema: macro, type: schema || undefined, payloadFields: collectGatePayloadFields(payload), chainFields: macro ? null : collectGateChainFields(payload) });
if (macro) base.macroSummary = macroSummary(payload);
if (!isString(tuple.signature)) return { valid: false, error: 'missing_signature', ...base };

@@ -153,5 +158,16 @@ if (!isString(tuple.digest) || !HEX_64.test(tuple.digest)) return { valid: false, error: 'malformed_hex', ...base, detail: 'tuple digest must be 64 lowercase hex characters' };

}
const semanticErrors = schemaErrors(payload);
const semanticErrors = macro ? macroSchemaErrors(payload) : schemaErrors(payload);
if (semanticErrors.length) return { valid: false, error: 'schema_invalid', ...base, digest: tuple.digest, publicKey: tuple.verification_key, detail: semanticErrors.join('; '), semanticErrors };
return { valid: true, ...base, digest: tuple.digest, publicKey: tuple.verification_key, keySource: pinned ? 'embedded-tuple (pinned via --key)' : 'embedded-tuple', algorithm: 'ed25519', proves: GATE_PROVES, limitations: GATE_LIMITATIONS };
return {
valid: true,
...base,
digest: tuple.digest,
publicKey: tuple.verification_key,
keySource: pinned ? 'embedded-tuple (pinned via --key)' : 'embedded-tuple',
signerPinned: pinned,
identityStatus: pinned ? 'pinned_expected_key' : 'embedded_key_only',
algorithm: 'ed25519',
proves: macro ? MACRO_PROVES : GATE_PROVES,
limitations: macro ? MACRO_LIMITATIONS : GATE_LIMITATIONS,
};
}

@@ -276,2 +292,23 @@

if (e.approval) add(e.approval, 'approval', i, approvalCheck(e.approval, parent, parent?.digest), false);
// Execution evidence requires a RELEASED decision. An ALLOW parent is
// released by definition; an APPROVAL_REQUIRED parent is released only by
// a present approval whose decision is "approved" (its own crypto and
// chain validity are checked above). Fills under a DENY, REVIEW, held, or
// declined parent are evidence of an unauthorized execution and fail the
// bundle even when every signature is individually valid.
const fillsPresent = Array.isArray(e.fills) && e.fills.length > 0;
if (fillsPresent) {
const decision = parent?.payload?.decision;
const released = decision === 'ALLOW'
|| (decision === 'APPROVAL_REQUIRED' && e.approval?.payload?.decision === 'approved');
results.chainChecks++;
if (!released) {
results.valid = false;
results.chainFailed++;
const why = decision === 'APPROVAL_REQUIRED'
? (e.approval ? `approval decision is ${JSON.stringify(e.approval?.payload?.decision)}` : 'no approval is present')
: `parent decision is ${JSON.stringify(decision)}`;
results.errors.push(`[chain] Entry ${i + 1}: fills present but the decision was never released (${why})`);
}
}
const fillsByDigest = new Map();

@@ -278,0 +315,0 @@ for (const fill of Array.isArray(e.fills) ? e.fills : []) { const err = fillCheck(fill, parent, legsById, legTuples); add(fill, 'fill', i, err, false); fillsByDigest.set(fill?.digest, fill); }

@@ -213,2 +213,59 @@ /**

/**
* Render the salient-field lines for a recognized macro snapshot summary.
*
* @param {Object} s macroSummary object from engines/macro-snapshot.js
* @returns {string[]}
*/
function macroSummaryLines(s) {
const lines = [];
if (s.description) lines.push(` Snapshot: ${dim(s.description)}`);
if (s.as_of) lines.push(` As of: ${dim(s.as_of)}`);
switch (s.schema) {
case 'scopeblind.macro.market-state/1':
lines.push(` Class: ${s.classification}${s.confidence !== undefined ? dim(` (confidence ${s.confidence})`) : ''}`);
if (s.pillars) lines.push(` Pillars: ${dim(Object.entries(s.pillars).map(([k, v]) => `${k} ${v >= 0 ? '+' : ''}${v}`).join(', '))}`);
break;
case 'scopeblind.macro.regime-snapshot/1':
lines.push(` Regime: ${s.regime}${s.candidate_regime && s.candidate_regime !== s.regime ? dim(` (candidate ${s.candidate_regime})`) : ''}`);
if (s.liquidity_overlay) lines.push(` Liquidity: ${s.liquidity_overlay}`);
if (s.confidence !== undefined) lines.push(` Confidence: ${dim(String(s.confidence))}`);
break;
case 'scopeblind.macro.tape-snapshot/1':
lines.push(` Tape type: ${s.tape_type}${s.material !== undefined ? dim(` (${s.material ? 'material' : 'immaterial'})`) : ''}`);
if (s.coherence !== undefined) lines.push(` Coherence: ${dim(String(s.coherence))}`);
if (s.attribution_tier) lines.push(` Attributed: ${dim(s.attribution_tier)}`);
break;
case 'scopeblind.macro.vulnerability/1':
if (s.regime || s.market_state) lines.push(` Posture: ${dim([s.regime, s.market_state].filter(Boolean).join(' / '))}`);
if (Array.isArray(s.top_vulnerabilities) && s.top_vulnerabilities.length) {
lines.push(` Top risk: ${dim(s.top_vulnerabilities.map((v) => `${v.factor} (pain ${v.pain})`).join(', '))}`);
}
break;
case 'scopeblind.macro.alert/1':
lines.push(` Severity: ${s.severity}${s.kind ? dim(` (${s.kind})`) : ''}`);
if (s.title) lines.push(` Title: ${s.title}`);
break;
case 'scopeblind.macro.journal-entry/1':
if (s.author) lines.push(` Author: ${s.author}`);
lines.push(` References: ${dim(`${s.reference_count} signed snapshot(s)`)}`);
break;
case 'scopeblind.macro.track-record-manifest/1':
lines.push(` Inventory: ${dim(`${s.snapshot_count} snapshots, ${s.journal_count} journal entries`)}`);
break;
case 'scopeblind.macro.transparency-head/1':
if (s.log_id) lines.push(` Log: ${dim(s.log_id)}`);
lines.push(` Tree size: ${dim(`${s.tree_size} leaves`)}`);
if (s.root_hash) lines.push(` Root: ${dim(`${String(s.root_hash).slice(0, 16)}...`)}`);
break;
case 'scopeblind.macro.transparency-witness/1':
if (s.head_digest) lines.push(` Head: ${dim(`${String(s.head_digest).slice(0, 16)}...`)}`);
lines.push(` Tree size: ${dim(`${s.tree_size} leaves`)}`);
break;
default:
break;
}
return lines;
}
/**
* Format a ScopeBlind Gate receipt-tuple result.

@@ -235,7 +292,9 @@ *

lines.push(`\n${icon} Signature: ${status}`);
lines.push(` Format: ScopeBlind Gate receipt tuple`);
lines.push(` Format: ${result.macroSchema ? 'ScopeBlind macro-engine snapshot' : 'ScopeBlind Gate receipt tuple'}`);
if (result.schema) {
const recog = result.schemaRecognized
? dim('(recognized)')
: yellow('(unrecognized schema; verified as a generic tuple)');
const recog = result.macroSchema && result.schemaRecognized
? dim('(recognized macro schema)')
: result.schemaRecognized
? dim('(recognized)')
: yellow('(unrecognized schema; verified as a generic tuple)');
lines.push(` Schema: ${result.schema} ${recog}`);

@@ -245,6 +304,9 @@ } else {

}
if (result.macroSummary) {
for (const line of macroSummaryLines(result.macroSummary)) lines.push(line);
}
if (result.algorithm) lines.push(` Algorithm: ${result.algorithm} (over the SHA-256 payload digest)`);
if (result.digest) lines.push(` Digest: ${dim(result.digest)}`);
if (result.recomputedDigest) lines.push(` Recomputed: ${red(result.recomputedDigest)}`);
if (result.publicKey) lines.push(` Signer: ${dim(result.publicKey)}`);
if (result.publicKey) lines.push(` Signer: ${result.signerLabel ? bold(result.signerLabel) + ' ' : ''}${dim(result.publicKey)}`);
if (result.keySource) lines.push(` Key: ${result.keySource}`);

@@ -330,3 +392,3 @@

if (result.algorithm) lines.push(` Algorithm: ${result.algorithm} ${dim('(over the canonical action payload, not a digest)')}`);
if (result.publicKey) lines.push(` Signer: ${dim(result.publicKey)}`);
if (result.publicKey) lines.push(` Signer: ${result.signerLabel ? bold(result.signerLabel) + ' ' : ''}${dim(result.publicKey)}`);
if (result.keySource) lines.push(` Key: ${result.keySource}`);

@@ -380,2 +442,78 @@

/**
* Format a Trusted Context Pack result: the signed attestation that a source file
* parsed to this context at this confidence and freshness. The output leads with
* the signer and the gate decision (usable / needs approval / blocked), names the
* source type, and is explicit that this attests the parse, not the provenance.
*
* @param {Object} result from src/engines/trusted-context-pack.js
* @param {Object} opts cli options
* @returns {string}
*/
export function formatTrustedContextPackResult(result, opts = {}) {
const lines = [];
if (result.valid && result.publicKey && result.publicKey.length === 64 && !isCI && !opts.noSigil) {
lines.push('');
lines.push(renderTerminalSigil(result.publicKey));
}
const icon = result.valid ? green('✓') : red('✗');
const status = result.valid ? green('VALID') : red('INVALID');
lines.push(`\n${icon} Signature: ${status}`);
lines.push(` Format: ScopeBlind Trusted Context Pack`);
if (result.schema) {
lines.push(` Schema: ${result.schema} ${result.schemaRecognized ? dim('(recognized)') : yellow('(unrecognized)')}`);
}
const pf = result.payloadFields || {};
if (pf.source_type) lines.push(` Source: ${pf.source_type}${pf.source_format ? dim(` (${pf.source_format})`) : ''}`);
if (pf.file_name) lines.push(` File: ${pf.file_name}`);
if (pf.file_hash) lines.push(` File hash: ${dim(`sha256:${String(pf.file_hash).slice(0, 16)}…`)}`);
// The gate decision is the headline: usable feeds a decision, the others do not.
const gate = result.gateStatus || pf.gate_status;
if (gate) {
const tone = gate === 'usable' ? green(gate) : gate === 'needs_approval' ? yellow(gate) : red(gate);
const note = gate === 'usable' ? 'may feed a gate decision'
: gate === 'needs_approval' ? 'held: requires explicit human approval before use'
: 'blocked: cannot feed a decision';
lines.push(` Gate: ${tone} ${dim(`(${note})`)}`);
}
if (result.confidence !== undefined) lines.push(` Confidence: ${result.confidence}`);
if (pf.freshness) {
const dated = pf.freshness.as_of ? `as of ${String(pf.freshness.as_of).slice(0, 10)}` : yellow('no as-of date');
const fresh = pf.freshness.stale ? red('(stale)') : dim('(fresh)');
lines.push(` Freshness: ${dated} ${fresh}`);
}
if (Array.isArray(pf.warnings) && pf.warnings.length) {
lines.push(` ${bold('Warnings:')}`);
for (const w of pf.warnings) lines.push(` ${yellow('!')} ${dim(w)}`);
}
if (result.algorithm) lines.push(` Algorithm: ${result.algorithm} ${dim('(over the SHA-256 payload digest)')}`);
if (result.digest) lines.push(` Digest: ${dim(result.digest)}`);
if (result.recomputedDigest) lines.push(` Recomputed: ${red(result.recomputedDigest)}`);
if (result.publicKey) lines.push(` Signer: ${result.signerLabel ? bold(result.signerLabel) + ' ' : ''}${dim(result.publicKey)}`);
if (result.keySource) lines.push(` Key: ${result.keySource}`);
if (result.error && !result.valid) {
lines.push(` Error: ${red(result.error)}`);
if (result.error === 'invalid_signature') lines.push(` Detail: ${yellow('the signed bytes were altered or the key does not match; this pack was tampered with')}`);
else if (result.detail) lines.push(` Detail: ${yellow(result.detail)}`);
if (result.expectedKey) lines.push(` Expected: ${yellow(result.expectedKey)} ${dim('(--key)')}`);
}
if (result.valid && Array.isArray(result.proves)) {
lines.push(` ${bold('This proves:')}`);
for (const p of result.proves) lines.push(` ${green('•')} ${dim(p)}`);
lines.push(` ${bold('This does not prove:')}`);
for (const l of (result.limitations || [])) lines.push(` ${yellow('!')} ${dim(l)}`);
}
lines.push('');
lines.push(WAYFINDING);
lines.push('');
return lines.join('\n');
}
/**
* Format a ScopeBlind Gate evidence-bundle result. Crypto failures

@@ -440,2 +578,70 @@ * and chain failures are reported separately so a reader can tell

/**
* Format a ScopeBlind macro-engine track-record bundle result. Like the Gate
* bundle formatter, crypto failures and chain (single-signer / manifest /
* history) failures are reported separately.
*
* @param {Object} result from src/engines/macro-snapshot.js
* @param {Object} opts cli options
* @returns {string}
*/
export function formatMacroTrackRecordResult(result, opts = {}) {
const lines = [];
const icon = result.valid ? green('✓') : red('✗');
const status = result.valid ? green('VALID') : red('INVALID');
lines.push(`\n${icon} Macro track-record bundle: ${status}`);
lines.push(` Schema: ${result.schema || '(missing)'}`);
if (result.exportedAt) lines.push(` Exported: ${dim(result.exportedAt)}`);
if (result.period) lines.push(` Period: ${dim(`${result.period.from} → ${result.period.to}`)}`);
if (result.custody) lines.push(` Custody: ${dim(result.custody)}`);
lines.push(` Identity: ${result.signerPinned ? green('pinned expected key') : yellow('embedded key only — integrity, not operator identity')}`);
if (result.sequence) lines.push(` Sequence: ${result.sequence}`);
lines.push(` Snapshots: ${result.snapshotCount}`);
lines.push(` Journal: ${result.journalCount}`);
lines.push(` Records: ${result.total} (${green(String(result.passed))} passed, ${result.failed > 0 ? red(String(result.failed)) : '0'} failed)`);
const cryptoOk = result.total - result.cryptoFailed;
lines.push(` Signatures: ${result.cryptoFailed > 0 ? red(`${cryptoOk}/${result.total} valid`) : green(`${cryptoOk}/${result.total} valid`)}`);
const chainOk = result.chainChecks - result.chainFailed;
lines.push(` Chain links: ${result.chainFailed > 0 ? red(`${chainOk}/${result.chainChecks} consistent`) : green(`${chainOk}/${result.chainChecks} consistent`)}`);
if (result.manifestValid !== null) lines.push(` Signed manifest: ${result.manifestValid ? green('valid and exact') : red('missing or inconsistent')}`);
lines.push(` Single-key consistency: ${result.singleSigner ? green('yes') : red('no')}`);
lines.push(` Append-only history: ${result.historyChainValid === true ? green('linked and retained') : result.historyChainValid === false ? red('invalid') : yellow('not established by this export')}`);
lines.push(` Signed checkpoint: ${result.historyAnchored ? green('present') : yellow('absent')}`);
if (result.transparencyAnchor) {
const t = result.transparencyAnchor;
const leaves = t.tree_size !== null ? `${t.tree_size} leaves` : 'Merkle log';
if (t.anchor === 'witnessed') lines.push(` Transparency: ${green(`witness-anchored (Merkle log, ${leaves})`)}`);
else if (t.anchor === 'self_signed') lines.push(` Transparency: ${yellow(`self-signed (Merkle log, ${leaves})`)}`);
else lines.push(` Transparency: ${red('not anchored')}`);
}
if (result.historyHeadPinned) lines.push(` History head: ${green('matches independently pinned head')}`);
if (result.anchorHeadPinned) lines.push(` Anchor head: ${green('matches independently pinned head')}`);
if (Array.isArray(result.signers) && result.signers.length > 0) {
lines.push(` ${bold('Signing keys seen:')}`);
for (const s of result.signers) {
const tag = s.isModelKey ? green('model key') : yellow('other key');
lines.push(` ${dim(s.key)} ${tag} ${dim(`(${s.roles.join(', ')})`)}`);
}
}
if (Array.isArray(result.errors) && result.errors.length > 0) {
lines.push(`\n ${red('Failures:')} ${dim('([crypto] record forged or modified; [chain] custody, manifest, or history-head inconsistent)')}`);
for (const e of result.errors) lines.push(` ${red('•')} ${e}`);
}
if (result.valid) {
lines.push('');
lines.push(` ${bold('This proves:')}`);
for (const p of (result.proves || [])) lines.push(` ${green('•')} ${dim(p)}`);
lines.push(` ${bold('This does not prove:')}`);
for (const l of (result.limitations || [])) lines.push(` ${yellow('!')} ${dim(l)}`);
}
lines.push('');
lines.push(WAYFINDING);
lines.push('');
return lines.join('\n');
}
export function formatKuResult(result, opts = {}) {

@@ -442,0 +648,0 @@ const lines = [];