@usesigil/kit 0.15.0 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (229) hide show
  1. package/dist/agent-bootstrap.d.ts +118 -0
  2. package/dist/agent-bootstrap.d.ts.map +1 -0
  3. package/dist/agent-bootstrap.js +211 -0
  4. package/dist/agent-bootstrap.js.map +1 -0
  5. package/dist/agent-errors.d.ts +3 -3
  6. package/dist/agent-errors.d.ts.map +1 -1
  7. package/dist/agent-errors.js +227 -142
  8. package/dist/agent-errors.js.map +1 -1
  9. package/dist/build-unsigned.d.ts +152 -0
  10. package/dist/build-unsigned.d.ts.map +1 -0
  11. package/dist/build-unsigned.js +152 -0
  12. package/dist/build-unsigned.js.map +1 -0
  13. package/dist/constraints/index.d.ts +23 -0
  14. package/dist/constraints/index.d.ts.map +1 -0
  15. package/dist/constraints/index.js +24 -0
  16. package/dist/constraints/index.js.map +1 -0
  17. package/dist/create-vault.d.ts +10 -1
  18. package/dist/create-vault.d.ts.map +1 -1
  19. package/dist/create-vault.js +10 -2
  20. package/dist/create-vault.js.map +1 -1
  21. package/dist/dashboard/constraint-builders.d.ts +82 -0
  22. package/dist/dashboard/constraint-builders.d.ts.map +1 -0
  23. package/dist/dashboard/constraint-builders.js +204 -0
  24. package/dist/dashboard/constraint-builders.js.map +1 -0
  25. package/dist/dashboard/errors.d.ts +37 -0
  26. package/dist/dashboard/errors.d.ts.map +1 -1
  27. package/dist/dashboard/errors.js +76 -0
  28. package/dist/dashboard/errors.js.map +1 -1
  29. package/dist/dashboard/from-json.d.ts.map +1 -1
  30. package/dist/dashboard/from-json.js +1 -2
  31. package/dist/dashboard/from-json.js.map +1 -1
  32. package/dist/dashboard/index.d.ts +29 -3
  33. package/dist/dashboard/index.d.ts.map +1 -1
  34. package/dist/dashboard/index.js +36 -1
  35. package/dist/dashboard/index.js.map +1 -1
  36. package/dist/dashboard/mutations.d.ts +60 -1
  37. package/dist/dashboard/mutations.d.ts.map +1 -1
  38. package/dist/dashboard/mutations.js +127 -20
  39. package/dist/dashboard/mutations.js.map +1 -1
  40. package/dist/dashboard/post-assertion-validation.d.ts +88 -0
  41. package/dist/dashboard/post-assertion-validation.d.ts.map +1 -0
  42. package/dist/dashboard/post-assertion-validation.js +191 -0
  43. package/dist/dashboard/post-assertion-validation.js.map +1 -0
  44. package/dist/dashboard/reads.d.ts +93 -1
  45. package/dist/dashboard/reads.d.ts.map +1 -1
  46. package/dist/dashboard/reads.js +238 -9
  47. package/dist/dashboard/reads.js.map +1 -1
  48. package/dist/dashboard/types.d.ts +147 -11
  49. package/dist/dashboard/types.d.ts.map +1 -1
  50. package/dist/errors/codes.js +1 -1
  51. package/dist/events.d.ts.map +1 -1
  52. package/dist/events.js +2 -1
  53. package/dist/events.js.map +1 -1
  54. package/dist/generated/accounts/pendingAgentPermissionsUpdate.d.ts +12 -0
  55. package/dist/generated/accounts/pendingAgentPermissionsUpdate.d.ts.map +1 -1
  56. package/dist/generated/accounts/pendingAgentPermissionsUpdate.js +3 -1
  57. package/dist/generated/accounts/pendingAgentPermissionsUpdate.js.map +1 -1
  58. package/dist/generated/accounts/pendingCloseConstraints.d.ts +12 -0
  59. package/dist/generated/accounts/pendingCloseConstraints.d.ts.map +1 -1
  60. package/dist/generated/accounts/pendingCloseConstraints.js +4 -2
  61. package/dist/generated/accounts/pendingCloseConstraints.js.map +1 -1
  62. package/dist/generated/accounts/pendingConstraintsUpdate.d.ts +14 -0
  63. package/dist/generated/accounts/pendingConstraintsUpdate.d.ts.map +1 -1
  64. package/dist/generated/accounts/pendingConstraintsUpdate.js +4 -2
  65. package/dist/generated/accounts/pendingConstraintsUpdate.js.map +1 -1
  66. package/dist/generated/accounts/pendingPolicyUpdate.d.ts +24 -4
  67. package/dist/generated/accounts/pendingPolicyUpdate.d.ts.map +1 -1
  68. package/dist/generated/accounts/pendingPolicyUpdate.js +6 -4
  69. package/dist/generated/accounts/pendingPolicyUpdate.js.map +1 -1
  70. package/dist/generated/accounts/policyConfig.d.ts +28 -10
  71. package/dist/generated/accounts/policyConfig.d.ts.map +1 -1
  72. package/dist/generated/accounts/policyConfig.js +4 -4
  73. package/dist/generated/accounts/policyConfig.js.map +1 -1
  74. package/dist/generated/accounts/sessionAuthority.d.ts +18 -4
  75. package/dist/generated/accounts/sessionAuthority.d.ts.map +1 -1
  76. package/dist/generated/accounts/sessionAuthority.js +3 -3
  77. package/dist/generated/accounts/sessionAuthority.js.map +1 -1
  78. package/dist/generated/errors/sigil.d.ts +95 -81
  79. package/dist/generated/errors/sigil.d.ts.map +1 -1
  80. package/dist/generated/errors/sigil.js +107 -86
  81. package/dist/generated/errors/sigil.js.map +1 -1
  82. package/dist/generated/event-discriminators.d.ts.map +1 -1
  83. package/dist/generated/event-discriminators.js +2 -1
  84. package/dist/generated/event-discriminators.js.map +1 -1
  85. package/dist/generated/instructions/cleanupOrphanConstraintsPda.d.ts +67 -0
  86. package/dist/generated/instructions/cleanupOrphanConstraintsPda.d.ts.map +1 -0
  87. package/dist/generated/instructions/cleanupOrphanConstraintsPda.js +120 -0
  88. package/dist/generated/instructions/cleanupOrphanConstraintsPda.js.map +1 -0
  89. package/dist/generated/instructions/freezeVault.d.ts +8 -5
  90. package/dist/generated/instructions/freezeVault.d.ts.map +1 -1
  91. package/dist/generated/instructions/freezeVault.js +14 -3
  92. package/dist/generated/instructions/freezeVault.js.map +1 -1
  93. package/dist/generated/instructions/index.d.ts +1 -0
  94. package/dist/generated/instructions/index.d.ts.map +1 -1
  95. package/dist/generated/instructions/index.js +1 -0
  96. package/dist/generated/instructions/index.js.map +1 -1
  97. package/dist/generated/instructions/initializeVault.d.ts +0 -4
  98. package/dist/generated/instructions/initializeVault.d.ts.map +1 -1
  99. package/dist/generated/instructions/initializeVault.js +0 -2
  100. package/dist/generated/instructions/initializeVault.js.map +1 -1
  101. package/dist/generated/instructions/queuePolicyUpdate.d.ts +8 -8
  102. package/dist/generated/instructions/queuePolicyUpdate.d.ts.map +1 -1
  103. package/dist/generated/instructions/queuePolicyUpdate.js +4 -4
  104. package/dist/generated/instructions/queuePolicyUpdate.js.map +1 -1
  105. package/dist/generated/programs/sigil.d.ts +29 -25
  106. package/dist/generated/programs/sigil.d.ts.map +1 -1
  107. package/dist/generated/programs/sigil.js +37 -25
  108. package/dist/generated/programs/sigil.js.map +1 -1
  109. package/dist/generated/types/accountConstraint.d.ts +16 -1
  110. package/dist/generated/types/accountConstraint.d.ts.map +1 -1
  111. package/dist/generated/types/accountConstraint.js +2 -0
  112. package/dist/generated/types/accountConstraint.js.map +1 -1
  113. package/dist/generated/types/accountConstraintZC.d.ts +7 -0
  114. package/dist/generated/types/accountConstraintZC.d.ts.map +1 -1
  115. package/dist/generated/types/accountConstraintZC.js +4 -2
  116. package/dist/generated/types/accountConstraintZC.js.map +1 -1
  117. package/dist/generated/types/constraintEntry.d.ts +0 -4
  118. package/dist/generated/types/constraintEntry.d.ts.map +1 -1
  119. package/dist/generated/types/constraintEntry.js +1 -3
  120. package/dist/generated/types/constraintEntry.js.map +1 -1
  121. package/dist/generated/types/constraintEntryZC.d.ts +17 -12
  122. package/dist/generated/types/constraintEntryZC.d.ts.map +1 -1
  123. package/dist/generated/types/constraintEntryZC.js +2 -2
  124. package/dist/generated/types/constraintEntryZC.js.map +1 -1
  125. package/dist/generated/types/index.d.ts +1 -0
  126. package/dist/generated/types/index.d.ts.map +1 -1
  127. package/dist/generated/types/index.js +1 -0
  128. package/dist/generated/types/index.js.map +1 -1
  129. package/dist/generated/types/orphanConstraintsPdaCleaned.d.ts +22 -0
  130. package/dist/generated/types/orphanConstraintsPdaCleaned.d.ts.map +1 -0
  131. package/dist/generated/types/orphanConstraintsPdaCleaned.js +26 -0
  132. package/dist/generated/types/orphanConstraintsPdaCleaned.js.map +1 -0
  133. package/dist/generated/types/vaultFrozen.d.ts +12 -0
  134. package/dist/generated/types/vaultFrozen.d.ts.map +1 -1
  135. package/dist/generated/types/vaultFrozen.js +3 -1
  136. package/dist/generated/types/vaultFrozen.js.map +1 -1
  137. package/dist/index.d.ts +11 -1
  138. package/dist/index.d.ts.map +1 -1
  139. package/dist/index.js +22 -1
  140. package/dist/index.js.map +1 -1
  141. package/dist/inscribe.d.ts +0 -4
  142. package/dist/inscribe.d.ts.map +1 -1
  143. package/dist/inscribe.js +0 -1
  144. package/dist/inscribe.js.map +1 -1
  145. package/dist/kit-adapter.d.ts +1 -1
  146. package/dist/kit-adapter.d.ts.map +1 -1
  147. package/dist/kit-adapter.js +1 -1
  148. package/dist/kit-adapter.js.map +1 -1
  149. package/dist/logger.d.ts +48 -0
  150. package/dist/logger.d.ts.map +1 -1
  151. package/dist/logger.js +36 -0
  152. package/dist/logger.js.map +1 -1
  153. package/dist/owner-transaction.d.ts +8 -0
  154. package/dist/owner-transaction.d.ts.map +1 -1
  155. package/dist/owner-transaction.js +1 -0
  156. package/dist/owner-transaction.js.map +1 -1
  157. package/dist/post-assertions/cross-field-lte.d.ts +134 -0
  158. package/dist/post-assertions/cross-field-lte.d.ts.map +1 -0
  159. package/dist/post-assertions/cross-field-lte.js +129 -0
  160. package/dist/post-assertions/cross-field-lte.js.map +1 -0
  161. package/dist/post-assertions/index.d.ts +28 -0
  162. package/dist/post-assertions/index.d.ts.map +1 -0
  163. package/dist/post-assertions/index.js +28 -0
  164. package/dist/post-assertions/index.js.map +1 -0
  165. package/dist/post-assertions/presets/flash-trade.d.ts +139 -0
  166. package/dist/post-assertions/presets/flash-trade.d.ts.map +1 -0
  167. package/dist/post-assertions/presets/flash-trade.js +154 -0
  168. package/dist/post-assertions/presets/flash-trade.js.map +1 -0
  169. package/dist/presets.d.ts +1 -7
  170. package/dist/presets.d.ts.map +1 -1
  171. package/dist/presets.js +0 -5
  172. package/dist/presets.js.map +1 -1
  173. package/dist/preview-create-vault.d.ts +280 -0
  174. package/dist/preview-create-vault.d.ts.map +1 -0
  175. package/dist/preview-create-vault.js +477 -0
  176. package/dist/preview-create-vault.js.map +1 -0
  177. package/dist/protocol-registry/annotations/drift.json +7 -0
  178. package/dist/protocol-registry/annotations/flash-trade.json +7 -0
  179. package/dist/protocol-registry/annotations/jupiter-borrow.json +7 -0
  180. package/dist/protocol-registry/annotations/jupiter-earn.json +7 -0
  181. package/dist/protocol-registry/annotations/jupiter-lend.json +7 -0
  182. package/dist/protocol-registry/annotations/jupiter.json +7 -0
  183. package/dist/protocol-registry/annotations/kamino.json +7 -0
  184. package/dist/protocol-registry/index.d.ts +45 -0
  185. package/dist/protocol-registry/index.d.ts.map +1 -0
  186. package/dist/protocol-registry/index.js +76 -0
  187. package/dist/protocol-registry/index.js.map +1 -0
  188. package/dist/protocol-tier.d.ts +157 -0
  189. package/dist/protocol-tier.d.ts.map +1 -0
  190. package/dist/protocol-tier.js +104 -0
  191. package/dist/protocol-tier.js.map +1 -0
  192. package/dist/seal.d.ts.map +1 -1
  193. package/dist/seal.js +26 -2
  194. package/dist/seal.js.map +1 -1
  195. package/dist/sigil.d.ts +0 -4
  196. package/dist/sigil.d.ts.map +1 -1
  197. package/dist/simulation.d.ts.map +1 -1
  198. package/dist/simulation.js +72 -91
  199. package/dist/simulation.js.map +1 -1
  200. package/dist/testing/devnet.d.ts.map +1 -1
  201. package/dist/testing/devnet.js +0 -1
  202. package/dist/testing/devnet.js.map +1 -1
  203. package/dist/testing/errors/expect.d.ts +137 -0
  204. package/dist/testing/errors/expect.d.ts.map +1 -0
  205. package/dist/testing/errors/expect.js +372 -0
  206. package/dist/testing/errors/expect.js.map +1 -0
  207. package/dist/testing/errors/index.d.ts +3 -0
  208. package/dist/testing/errors/index.d.ts.map +1 -0
  209. package/dist/testing/errors/index.js +8 -0
  210. package/dist/testing/errors/index.js.map +1 -0
  211. package/dist/testing/errors/names.generated.d.ts +188 -0
  212. package/dist/testing/errors/names.generated.d.ts.map +1 -0
  213. package/dist/testing/errors/names.generated.js +183 -0
  214. package/dist/testing/errors/names.generated.js.map +1 -0
  215. package/dist/testing/index.d.ts +1 -0
  216. package/dist/testing/index.d.ts.map +1 -1
  217. package/dist/testing/index.js +8 -0
  218. package/dist/testing/index.js.map +1 -1
  219. package/dist/testing/mock-rpc.d.ts +8 -0
  220. package/dist/testing/mock-rpc.d.ts.map +1 -1
  221. package/dist/testing/mock-rpc.js +14 -0
  222. package/dist/testing/mock-rpc.js.map +1 -1
  223. package/dist/testing/mock-state.js +2 -2
  224. package/dist/testing/mock-state.js.map +1 -1
  225. package/package.json +15 -3
  226. package/dist/integrations/protocol-handler.d.ts +0 -59
  227. package/dist/integrations/protocol-handler.d.ts.map +0 -1
  228. package/dist/integrations/protocol-handler.js +0 -9
  229. package/dist/integrations/protocol-handler.js.map +0 -1
@@ -0,0 +1,191 @@
1
+ // ─── Constants (pinned to Rust source) ────────────────────────────────────
2
+ // These MUST match the Rust constants. If they drift, the validator will
3
+ // pass inputs the program then rejects (or vice-versa), producing confusing
4
+ // round-trip failures. Keep in sync with `programs/sigil/src/state/*.rs`.
5
+ /** `programs/sigil/src/state/post_assertions.rs:7` */
6
+ const MAX_POST_ASSERTION_ENTRIES = 4;
7
+ /** `programs/sigil/src/state/constraints.rs:9` */
8
+ const MAX_CONSTRAINT_VALUE_LEN = 32;
9
+ /** Operator IDs (0..=6) — see `programs/sigil/src/state/constraints.rs ConstraintOperator`. */
10
+ const MAX_OPERATOR_VALUE = 6;
11
+ /** AssertionMode IDs (0..=3) — see `programs/sigil/src/state/post_assertions.rs AssertionMode`. */
12
+ const MAX_ASSERTION_MODE_VALUE = 3;
13
+ /** CrossFieldLte enable bit. Every other bit is reserved; validator rejects unknown flags. */
14
+ const CROSS_FIELD_LTE_FLAG = 0x01;
15
+ /** CrossField payloads are parsed as u64 on-chain; 8 is the max byte length. */
16
+ const CROSS_FIELD_MAX_VALUE_LEN = 8;
17
+ /** Delta modes (MaxDecrease=1, MaxIncrease=2, NoChange=3) also parse as u64. */
18
+ const DELTA_MAX_VALUE_LEN = 8;
19
+ /**
20
+ * Numeric `DxError.code` for every PostAssertion validation failure.
21
+ *
22
+ * All validation-class failures share this single numeric code — the more
23
+ * specific `validationCode` string discriminates. 7008 is the existing SDK
24
+ * "PRECHECK_FAILED" bucket (see `dashboard/errors.ts` SIGIL_ERROR_TO_NUMERIC),
25
+ * which is semantically correct: the client-side validator IS a pre-check
26
+ * for the on-chain validate_entries call.
27
+ */
28
+ export const DX_CODE_POST_ASSERTION_VALIDATION = 7008;
29
+ /**
30
+ * Thrown by {@link validatePostAssertionEntries} when an entry fails any
31
+ * check the on-chain program would enforce.
32
+ *
33
+ * Structurally compatible with `DxError` — exposes `code: number`,
34
+ * `message: string`, and `recovery: string[]` so FE can render the error
35
+ * without re-wrapping. Also carries the typed `validationCode` (the
36
+ * specific failure reason) and `entryIndex` (the zero-based index of the
37
+ * offending entry, or `null` for batch-level failures).
38
+ *
39
+ * Mutation wrappers re-throw this instance directly — they do NOT wrap
40
+ * via `toDxError`. Wrapping would collapse the typed fields into
41
+ * `DX_ERROR_CODE_UNMAPPED` (7999), breaking the file docblock's promise
42
+ * that the FE can branch on `validationCode`.
43
+ */
44
+ export class PostAssertionValidationError extends Error {
45
+ code;
46
+ validationCode;
47
+ entryIndex;
48
+ recovery;
49
+ /**
50
+ * Always `false` — this error is thrown at CLIENT validation time,
51
+ * BEFORE any RPC round-trip. Present to satisfy the DxError structural
52
+ * contract (every DxError carries `onChainReverted`; see FE↔BE
53
+ * contract v2.2 C2). Pre-existing callers need no migration.
54
+ */
55
+ onChainReverted = false;
56
+ constructor(validationCode, entryIndex, message) {
57
+ super(message);
58
+ this.name = "PostAssertionValidationError";
59
+ this.code = DX_CODE_POST_ASSERTION_VALIDATION;
60
+ this.validationCode = validationCode;
61
+ this.entryIndex = entryIndex;
62
+ this.recovery = [
63
+ entryIndex !== null
64
+ ? `Fix PostAssertion entry at index ${entryIndex} (${validationCode}) and retry.`
65
+ : `Fix PostAssertion batch (${validationCode}) and retry.`,
66
+ ];
67
+ // Preserve prototype chain under ES5 target
68
+ Object.setPrototypeOf(this, PostAssertionValidationError.prototype);
69
+ }
70
+ }
71
+ /**
72
+ * Validate a batch of PostAssertionEntry values against the exact rules
73
+ * the on-chain program enforces.
74
+ *
75
+ * Throws on the FIRST failing check (same as the Rust `for entry in entries`
76
+ * loop). Use a try/catch to recover; the error's `validationCode` +
77
+ * `entryIndex` identify the offending entry.
78
+ *
79
+ * @param entries Batch to check. Must be 1..=4 entries.
80
+ * @throws {PostAssertionValidationError} with the specific failure code.
81
+ */
82
+ export function validatePostAssertionEntries(entries) {
83
+ // Input-shape guard: TS doesn't enforce runtime shape, so an `any` caller
84
+ // can pass null/undefined/non-array without a compiler warning. Without
85
+ // this, `entries.length` would throw a cryptic TypeError that `toDxError`
86
+ // collapses to code 7999.
87
+ if (!Array.isArray(entries)) {
88
+ throw new PostAssertionValidationError("entries_not_an_array", null, `PostAssertion entries must be an array, got ${entries === null ? "null" : typeof entries}`);
89
+ }
90
+ // Batch-level: entry count must be 1..=MAX.
91
+ if (entries.length === 0 || entries.length > MAX_POST_ASSERTION_ENTRIES) {
92
+ throw new PostAssertionValidationError("entry_count_out_of_range", null, `PostAssertion entry count must be 1..=${MAX_POST_ASSERTION_ENTRIES}, got ${entries.length}`);
93
+ }
94
+ entries.forEach((entry, index) => {
95
+ // Per-slot null guard — forEach skips truly empty slots but an array
96
+ // literal `[null, validEntry]` yields `entry === null` at index 0.
97
+ if (entry == null) {
98
+ throw new PostAssertionValidationError("entries_contain_null", index, `PostAssertion[${index}]: entry is ${entry === null ? "null" : "undefined"}`);
99
+ }
100
+ validateSingleEntry(entry, index);
101
+ });
102
+ }
103
+ // ─── Internal ─────────────────────────────────────────────────────────────
104
+ /**
105
+ * Guard that rejects non-integer, out-of-range, non-finite, or negative
106
+ * numeric field values at the validator layer — BEFORE Codama's u8/u16/u32
107
+ * encoders would either silently truncate (`8.5` → `8`) or throw a
108
+ * different error class (`-1` → SolanaError).
109
+ *
110
+ * Having a single typed rejection point means every invalid numeric input
111
+ * surfaces as `PostAssertionValidationError` with the field's specific
112
+ * `validationCode`, rather than a grab-bag of Codama runtime failures.
113
+ */
114
+ function requireUintInRange(value, field, max, code, index) {
115
+ if (typeof value !== "number" ||
116
+ !Number.isInteger(value) ||
117
+ value < 0 ||
118
+ value > max) {
119
+ throw new PostAssertionValidationError(code, index, `PostAssertion[${index}]: ${field} must be an integer 0..=${max}, got ${JSON.stringify(value)} (${typeof value})`);
120
+ }
121
+ }
122
+ function validateSingleEntry(entry, index) {
123
+ // Strict numeric shape checks — integer, non-negative, fits the on-chain
124
+ // field width. Catch non-integer (e.g. 8.5) and negative (-1) inputs that
125
+ // one-sided `> MAX` comparisons would miss.
126
+ requireUintInRange(entry.offset, "offset", 0xffff, "offset_out_of_range", index);
127
+ requireUintInRange(entry.valueLen, "value_len", MAX_CONSTRAINT_VALUE_LEN, "value_len_out_of_range", index);
128
+ requireUintInRange(entry.operator, "operator", MAX_OPERATOR_VALUE, "operator_out_of_range", index);
129
+ requireUintInRange(entry.assertionMode, "assertion_mode", MAX_ASSERTION_MODE_VALUE, "assertion_mode_out_of_range", index);
130
+ requireUintInRange(entry.crossFieldOffsetB, "cross_field_offset_b", 0xffff, "cross_field_offset_b_out_of_range", index);
131
+ requireUintInRange(entry.crossFieldMultiplierBps, "cross_field_multiplier_bps", 0xffffffff, "cross_field_multiplier_bps_out_of_range", index);
132
+ requireUintInRange(entry.crossFieldFlags, "cross_field_flags", 0xff, "cross_field_flags_out_of_range", index);
133
+ // value_len must additionally be >= 1 (the shared range check allows 0;
134
+ // on-chain requires > 0 because a zero-length value is a semantic no-op).
135
+ if (entry.valueLen === 0) {
136
+ throw new PostAssertionValidationError("value_len_out_of_range", index, `PostAssertion[${index}]: value_len must be 1..=${MAX_CONSTRAINT_VALUE_LEN}, got 0`);
137
+ }
138
+ // expected_value must be at least `value_len` bytes. Callers that pass
139
+ // a shorter buffer would have the on-chain program reject the entry —
140
+ // catch here instead.
141
+ if (entry.expectedValue.length < entry.valueLen) {
142
+ throw new PostAssertionValidationError("expected_value_too_short", index, `PostAssertion[${index}]: expected_value has ${entry.expectedValue.length} bytes but value_len=${entry.valueLen} (must be >= value_len)`);
143
+ }
144
+ // Delta modes (1/2/3) compare the pre/post snapshot as u64 — so the
145
+ // expected-value payload must fit in 8 bytes. The on-chain program
146
+ // enforces this; we mirror the check here.
147
+ if (entry.assertionMode >= 1 && entry.assertionMode <= 3) {
148
+ if (entry.valueLen > DELTA_MAX_VALUE_LEN) {
149
+ throw new PostAssertionValidationError("delta_mode_value_len_too_large", index, `PostAssertion[${index}]: delta assertion_mode=${entry.assertionMode} requires value_len <= ${DELTA_MAX_VALUE_LEN}, got ${entry.valueLen}`);
150
+ }
151
+ }
152
+ // CrossFieldLte enable bit. Since we already asserted integrality of
153
+ // crossFieldFlags above, the bitwise AND here is safe — no silent Int32
154
+ // truncation of a fractional input.
155
+ const crossFieldEnabled = (entry.crossFieldFlags & CROSS_FIELD_LTE_FLAG) !== 0;
156
+ if (crossFieldEnabled) {
157
+ // CrossFieldLte parses both field_A and field_B as u64 via le_bytes[0..8].
158
+ // Payload must fit. Upstream attacker path: value_len=16 with a crafted
159
+ // field would bypass the ratio check by silently truncating.
160
+ if (entry.valueLen > CROSS_FIELD_MAX_VALUE_LEN) {
161
+ throw new PostAssertionValidationError("cross_field_value_len_too_large", index, `PostAssertion[${index}]: CrossFieldLte requires value_len <= ${CROSS_FIELD_MAX_VALUE_LEN}, got ${entry.valueLen}`);
162
+ }
163
+ // CrossFieldLte is a ratio check and only composes with Absolute mode.
164
+ // Combining it with delta modes would read the snapshot as field_A,
165
+ // which is semantically nonsensical — the on-chain program hard-rejects.
166
+ if (entry.assertionMode !== 0) {
167
+ throw new PostAssertionValidationError("cross_field_requires_absolute_mode", index, `PostAssertion[${index}]: CrossFieldLte requires assertion_mode=0 (Absolute), got ${entry.assertionMode}`);
168
+ }
169
+ // multiplier_bps > 0. A zero multiplier collapses the ratio check to
170
+ // `field_A * 10000 <= 0 * field_B` (always false unless field_A == 0),
171
+ // which is either a no-op or a trap. Reject at authoring time.
172
+ if (entry.crossFieldMultiplierBps === 0) {
173
+ throw new PostAssertionValidationError("cross_field_multiplier_must_be_positive", index, `PostAssertion[${index}]: CrossFieldLte multiplier_bps must be > 0`);
174
+ }
175
+ // Only bit 0 is defined. Any other bit set indicates future-flag drift
176
+ // or misuse; the on-chain program rejects via `flags & 0xFE == 0`.
177
+ if ((entry.crossFieldFlags & 0xfe) !== 0) {
178
+ throw new PostAssertionValidationError("cross_field_unknown_flags", index, `PostAssertion[${index}]: cross_field_flags has reserved bits set: 0x${entry.crossFieldFlags.toString(16).padStart(2, "0")} (only bit 0 is defined)`);
179
+ }
180
+ }
181
+ else {
182
+ // CrossFieldLte disabled → both auxiliary fields MUST be zero.
183
+ // A nonzero value here is a callsite bug (forgot to clear fields after
184
+ // switching from CrossFieldLte to plain assertion) and the program
185
+ // rejects via matching check.
186
+ if (entry.crossFieldOffsetB !== 0 || entry.crossFieldMultiplierBps !== 0) {
187
+ throw new PostAssertionValidationError("cross_field_disabled_fields_must_be_zero", index, `PostAssertion[${index}]: CrossFieldLte disabled but cross_field_offset_b=${entry.crossFieldOffsetB}, cross_field_multiplier_bps=${entry.crossFieldMultiplierBps} (both must be 0)`);
188
+ }
189
+ }
190
+ }
191
+ //# sourceMappingURL=post-assertion-validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"post-assertion-validation.js","sourceRoot":"","sources":["../../src/dashboard/post-assertion-validation.ts"],"names":[],"mappings":"AA2BA,6EAA6E;AAC7E,yEAAyE;AACzE,4EAA4E;AAC5E,0EAA0E;AAE1E,sDAAsD;AACtD,MAAM,0BAA0B,GAAG,CAAC,CAAC;AACrC,kDAAkD;AAClD,MAAM,wBAAwB,GAAG,EAAE,CAAC;AAEpC,+FAA+F;AAC/F,MAAM,kBAAkB,GAAG,CAAC,CAAC;AAC7B,mGAAmG;AACnG,MAAM,wBAAwB,GAAG,CAAC,CAAC;AAEnC,8FAA8F;AAC9F,MAAM,oBAAoB,GAAG,IAAI,CAAC;AAClC,gFAAgF;AAChF,MAAM,yBAAyB,GAAG,CAAC,CAAC;AACpC,gFAAgF;AAChF,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAgC9B;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,iCAAiC,GAAG,IAAa,CAAC;AAE/D;;;;;;;;;;;;;;GAcG;AACH,MAAM,OAAO,4BAA6B,SAAQ,KAAK;IACrC,IAAI,CAAS;IACb,cAAc,CAA8B;IAC5C,UAAU,CAAgB;IAC1B,QAAQ,CAAW;IACnC;;;;;OAKG;IACa,eAAe,GAAY,KAAK,CAAC;IAEjD,YACE,cAA2C,EAC3C,UAAyB,EACzB,OAAe;QAEf,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,8BAA8B,CAAC;QAC3C,IAAI,CAAC,IAAI,GAAG,iCAAiC,CAAC;QAC9C,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;QACrC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,QAAQ,GAAG;YACd,UAAU,KAAK,IAAI;gBACjB,CAAC,CAAC,oCAAoC,UAAU,KAAK,cAAc,cAAc;gBACjF,CAAC,CAAC,4BAA4B,cAAc,cAAc;SAC7D,CAAC;QACF,4CAA4C;QAC5C,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,4BAA4B,CAAC,SAAS,CAAC,CAAC;IACtE,CAAC;CACF;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,4BAA4B,CAC1C,OAAsC;IAEtC,0EAA0E;IAC1E,wEAAwE;IACxE,0EAA0E;IAC1E,0BAA0B;IAC1B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,4BAA4B,CACpC,sBAAsB,EACtB,IAAI,EACJ,+CAA+C,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,OAAO,EAAE,CAC5F,CAAC;IACJ,CAAC;IAED,4CAA4C;IAC5C,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,MAAM,GAAG,0BAA0B,EAAE,CAAC;QACxE,MAAM,IAAI,4BAA4B,CACpC,0BAA0B,EAC1B,IAAI,EACJ,yCAAyC,0BAA0B,SAAS,OAAO,CAAC,MAAM,EAAE,CAC7F,CAAC;IACJ,CAAC;IAED,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;QAC/B,qEAAqE;QACrE,mEAAmE;QACnE,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;YAClB,MAAM,IAAI,4BAA4B,CACpC,sBAAsB,EACtB,KAAK,EACL,iBAAiB,KAAK,eAAe,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,EAAE,CAC7E,CAAC;QACJ,CAAC;QACD,mBAAmB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;AACL,CAAC;AAED,6EAA6E;AAE7E;;;;;;;;;GASG;AACH,SAAS,kBAAkB,CACzB,KAAa,EACb,KAAa,EACb,GAAW,EACX,IAAiC,EACjC,KAAa;IAEb,IACE,OAAO,KAAK,KAAK,QAAQ;QACzB,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC;QACxB,KAAK,GAAG,CAAC;QACT,KAAK,GAAG,GAAG,EACX,CAAC;QACD,MAAM,IAAI,4BAA4B,CACpC,IAAI,EACJ,KAAK,EACL,iBAAiB,KAAK,MAAM,KAAK,2BAA2B,GAAG,SAAS,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,OAAO,KAAK,GAAG,CAClH,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAyB,EAAE,KAAa;IACnE,yEAAyE;IACzE,0EAA0E;IAC1E,4CAA4C;IAC5C,kBAAkB,CAChB,KAAK,CAAC,MAAM,EACZ,QAAQ,EACR,MAAM,EACN,qBAAqB,EACrB,KAAK,CACN,CAAC;IACF,kBAAkB,CAChB,KAAK,CAAC,QAAQ,EACd,WAAW,EACX,wBAAwB,EACxB,wBAAwB,EACxB,KAAK,CACN,CAAC;IACF,kBAAkB,CAChB,KAAK,CAAC,QAAQ,EACd,UAAU,EACV,kBAAkB,EAClB,uBAAuB,EACvB,KAAK,CACN,CAAC;IACF,kBAAkB,CAChB,KAAK,CAAC,aAAa,EACnB,gBAAgB,EAChB,wBAAwB,EACxB,6BAA6B,EAC7B,KAAK,CACN,CAAC;IACF,kBAAkB,CAChB,KAAK,CAAC,iBAAiB,EACvB,sBAAsB,EACtB,MAAM,EACN,mCAAmC,EACnC,KAAK,CACN,CAAC;IACF,kBAAkB,CAChB,KAAK,CAAC,uBAAuB,EAC7B,4BAA4B,EAC5B,UAAU,EACV,yCAAyC,EACzC,KAAK,CACN,CAAC;IACF,kBAAkB,CAChB,KAAK,CAAC,eAAe,EACrB,mBAAmB,EACnB,IAAI,EACJ,gCAAgC,EAChC,KAAK,CACN,CAAC;IAEF,wEAAwE;IACxE,0EAA0E;IAC1E,IAAI,KAAK,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,4BAA4B,CACpC,wBAAwB,EACxB,KAAK,EACL,iBAAiB,KAAK,4BAA4B,wBAAwB,SAAS,CACpF,CAAC;IACJ,CAAC;IAED,uEAAuE;IACvE,sEAAsE;IACtE,sBAAsB;IACtB,IAAI,KAAK,CAAC,aAAa,CAAC,MAAM,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC;QAChD,MAAM,IAAI,4BAA4B,CACpC,0BAA0B,EAC1B,KAAK,EACL,iBAAiB,KAAK,yBAAyB,KAAK,CAAC,aAAa,CAAC,MAAM,wBAAwB,KAAK,CAAC,QAAQ,yBAAyB,CACzI,CAAC;IACJ,CAAC;IAED,oEAAoE;IACpE,mEAAmE;IACnE,2CAA2C;IAC3C,IAAI,KAAK,CAAC,aAAa,IAAI,CAAC,IAAI,KAAK,CAAC,aAAa,IAAI,CAAC,EAAE,CAAC;QACzD,IAAI,KAAK,CAAC,QAAQ,GAAG,mBAAmB,EAAE,CAAC;YACzC,MAAM,IAAI,4BAA4B,CACpC,gCAAgC,EAChC,KAAK,EACL,iBAAiB,KAAK,2BAA2B,KAAK,CAAC,aAAa,0BAA0B,mBAAmB,SAAS,KAAK,CAAC,QAAQ,EAAE,CAC3I,CAAC;QACJ,CAAC;IACH,CAAC;IAED,qEAAqE;IACrE,wEAAwE;IACxE,oCAAoC;IACpC,MAAM,iBAAiB,GACrB,CAAC,KAAK,CAAC,eAAe,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;IAEvD,IAAI,iBAAiB,EAAE,CAAC;QACtB,2EAA2E;QAC3E,wEAAwE;QACxE,6DAA6D;QAC7D,IAAI,KAAK,CAAC,QAAQ,GAAG,yBAAyB,EAAE,CAAC;YAC/C,MAAM,IAAI,4BAA4B,CACpC,iCAAiC,EACjC,KAAK,EACL,iBAAiB,KAAK,0CAA0C,yBAAyB,SAAS,KAAK,CAAC,QAAQ,EAAE,CACnH,CAAC;QACJ,CAAC;QAED,uEAAuE;QACvE,oEAAoE;QACpE,yEAAyE;QACzE,IAAI,KAAK,CAAC,aAAa,KAAK,CAAC,EAAE,CAAC;YAC9B,MAAM,IAAI,4BAA4B,CACpC,oCAAoC,EACpC,KAAK,EACL,iBAAiB,KAAK,8DAA8D,KAAK,CAAC,aAAa,EAAE,CAC1G,CAAC;QACJ,CAAC;QAED,qEAAqE;QACrE,uEAAuE;QACvE,+DAA+D;QAC/D,IAAI,KAAK,CAAC,uBAAuB,KAAK,CAAC,EAAE,CAAC;YACxC,MAAM,IAAI,4BAA4B,CACpC,yCAAyC,EACzC,KAAK,EACL,iBAAiB,KAAK,6CAA6C,CACpE,CAAC;QACJ,CAAC;QAED,uEAAuE;QACvE,mEAAmE;QACnE,IAAI,CAAC,KAAK,CAAC,eAAe,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YACzC,MAAM,IAAI,4BAA4B,CACpC,2BAA2B,EAC3B,KAAK,EACL,iBAAiB,KAAK,iDAAiD,KAAK,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,0BAA0B,CACrJ,CAAC;QACJ,CAAC;IACH,CAAC;SAAM,CAAC;QACN,+DAA+D;QAC/D,uEAAuE;QACvE,mEAAmE;QACnE,8BAA8B;QAC9B,IAAI,KAAK,CAAC,iBAAiB,KAAK,CAAC,IAAI,KAAK,CAAC,uBAAuB,KAAK,CAAC,EAAE,CAAC;YACzE,MAAM,IAAI,4BAA4B,CACpC,0CAA0C,EAC1C,KAAK,EACL,iBAAiB,KAAK,sDAAsD,KAAK,CAAC,iBAAiB,gCAAgC,KAAK,CAAC,uBAAuB,mBAAmB,CACpL,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -11,8 +11,9 @@
11
11
  * computed exactly once.
12
12
  */
13
13
  import type { Address, Rpc, SolanaRpcApi } from "../kit-adapter.js";
14
+ import type { Alert } from "../security-analytics.js";
14
15
  import type { VaultActivityItem } from "../event-analytics.js";
15
- import type { VaultState, AgentData, SpendingData, ActivityData, ActivityFilters, ActivityRow, HealthData, PolicyData, OverviewContext, OverviewData, GetOverviewOptions } from "./types.js";
16
+ import type { VaultState, AgentData, SpendingData, ActivityData, ActivityFilters, ActivityRow, HealthData, PolicyData, OverviewContext, OverviewData, GetOverviewOptions, RiskMetrics, AuditTrailEntry, AuditTrailOptions } from "./types.js";
16
17
  /**
17
18
  * Default size of the activity window included in `getOverview`. Consumers
18
19
  * may override via `GetOverviewOptions.activityLimit`.
@@ -135,4 +136,95 @@ export declare function getPolicy(rpc: Rpc<SolanaRpcApi>, vault: Address, networ
135
136
  * update", even on the `includeActivity: false` lightweight path.
136
137
  */
137
138
  export declare function getOverview(rpc: Rpc<SolanaRpcApi>, vault: Address, network: "devnet" | "mainnet", options?: GetOverviewOptions): Promise<OverviewData>;
139
+ /**
140
+ * Compose a single {@link AgentData} from a pre-fetched {@link OverviewContext}.
141
+ *
142
+ * Reuses {@link buildAgents} and filters to the requested address. Returns
143
+ * `null` when the agent is not registered in the vault — callers that want
144
+ * the throwing surface use `getAgentDetail` instead.
145
+ *
146
+ * Activity-derived fields (`lastActionType` / `lastActionProtocol` /
147
+ * `lastActionTimestamp` / `blockedCount24h`) follow the same defaulting rules
148
+ * as `buildAgents`: empty/zero when `ctx.activity` is undefined.
149
+ *
150
+ * @experimental Part of the `build*` composition surface (S10). Signature and
151
+ * JSON shape may shift before v1.0.
152
+ *
153
+ * @see OwnerClient.getAgentDetail — the stable single-call alternative.
154
+ */
155
+ export declare function buildAgentDetail(ctx: OverviewContext, agent: Address): AgentData | null;
156
+ /**
157
+ * Single-agent detail wrapper around {@link getAgentProfile} + activity
158
+ * enrichment. Resolves vault state, fetches the same 100-event activity
159
+ * window as `getAgents`, and returns the {@link AgentData} for the requested
160
+ * agent.
161
+ *
162
+ * Throws a typed {@link SigilSdkDomainError} (mapped through `toDxError` to
163
+ * `SIGIL_ERROR__SDK__INVALID_PARAMS`) when the agent is not registered in
164
+ * the vault. Same graceful-degradation pattern as `getAgents` for activity
165
+ * fetch failures: enrichment fields default to empty/zero rather than
166
+ * propagating the failure.
167
+ */
168
+ export declare function getAgentDetail(rpc: Rpc<SolanaRpcApi>, vault: Address, agent: Address, network: "devnet" | "mainnet"): Promise<AgentData>;
169
+ /**
170
+ * Map an {@link Alert}[] to the four-level UI risk badge. Critical wins over
171
+ * warning, warning wins over info; absence of any alerts is "low".
172
+ *
173
+ * Pure helper — exposed for direct testing. Most consumers use
174
+ * {@link getRiskMetrics}.
175
+ */
176
+ export declare function deriveRiskLevel(alerts: readonly Alert[]): RiskMetrics["riskLevel"];
177
+ /**
178
+ * Compute {@link RiskMetrics} from a pre-fetched {@link OverviewContext}.
179
+ *
180
+ * Combines:
181
+ * - {@link getSpendingVelocity}(state.tracker, now, state.globalBudget) →
182
+ * `currentRate` becomes `spendingVelocity`; `isAccelerating` and
183
+ * `timeToCapSeconds` flow through directly.
184
+ * - 24h cap projection → `capVelocity = currentRate * 24 / cap × 100`
185
+ * (clamped at 0 when cap is 0n).
186
+ * - {@link evaluateAlertConditions}(state, vault) → `riskLevel` via
187
+ * {@link deriveRiskLevel}. Uses `ctx.alerts` when memoized.
188
+ *
189
+ * @experimental Part of the `build*` composition surface (S11). Signature and
190
+ * JSON shape may shift before v1.0.
191
+ *
192
+ * @see OwnerClient.getRiskMetrics — the stable single-call alternative.
193
+ */
194
+ export declare function buildRiskMetrics(ctx: OverviewContext): RiskMetrics;
195
+ /**
196
+ * Risk-tilt summary for a vault — current spending velocity, daily-cap
197
+ * projection, and a four-level risk badge derived from the alert stream.
198
+ *
199
+ * One state resolution + one alert evaluation. Use this for the dashboard's
200
+ * "is something concerning right now?" indicator. For deeper inspection,
201
+ * pair with `getOverview` (which embeds the alert list) or the
202
+ * `evaluateAlertConditions` export.
203
+ */
204
+ export declare function getRiskMetrics(rpc: Rpc<SolanaRpcApi>, vault: Address, network: "devnet" | "mainnet"): Promise<RiskMetrics>;
205
+ /**
206
+ * Filter raw {@link VaultActivityItem}[] to the audit subset and map each to
207
+ * an {@link AuditTrailEntry}. Pure — no RPC, no time-based filtering.
208
+ *
209
+ * Used by both `getAuditTrail` (which then applies the optional `since`
210
+ * timestamp filter) and direct callers that already have an activity list.
211
+ *
212
+ * @experimental Part of the `build*` composition surface (S12).
213
+ */
214
+ export declare function buildAuditTrail(items: readonly VaultActivityItem[]): AuditTrailEntry[];
215
+ /**
216
+ * Governance + security audit trail — the policy/agent/security/escrow
217
+ * subset of the vault's activity stream.
218
+ *
219
+ * Use this for an admin-facing "what changed?" feed: policy queue/apply
220
+ * cycles, agent registrations, vault freeze/resume events, and escrow
221
+ * lifecycle. Trades and fund movements are excluded — they live in
222
+ * `getActivity()`.
223
+ *
224
+ * Activity fetch shape: one `getSignaturesForAddress` + up to `limit`
225
+ * sequential `getTransaction` calls (see {@link getVaultActivity}).
226
+ * Default limit is 100 — large enough to surface a few weeks of governance
227
+ * activity for a typical vault without inflating RPC cost.
228
+ */
229
+ export declare function getAuditTrail(rpc: Rpc<SolanaRpcApi>, vault: Address, network: "devnet" | "mainnet", opts?: AuditTrailOptions): Promise<AuditTrailEntry[]>;
138
230
  //# sourceMappingURL=reads.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"reads.d.ts","sourceRoot":"","sources":["../../src/dashboard/reads.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAkBpE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAgB/D,OAAO,KAAK,EACV,UAAU,EACV,SAAS,EACT,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,WAAW,EAEX,UAAU,EACV,UAAU,EAGV,eAAe,EACf,YAAY,EACZ,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAyBpB;;;;;;;GAOG;AACH,eAAO,MAAM,+BAA+B,MAAM,CAAC;AA6BnD;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,eAAe,GAAG,UAAU,CA4DhE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,eAAe,GAAG,SAAS,EAAE,CA2D7D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,eAAe,GAAG,YAAY,CA+ChE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,eAAe,GAAG,UAAU,CA+C5D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,eAAe,GAAG,UAAU,CA+G5D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,SAAS,iBAAiB,EAAE,GAClC,WAAW,EAAE,CAkCf;AAID,wBAAsB,aAAa,CACjC,GAAG,EAAE,GAAG,CAAC,YAAY,CAAC,EACtB,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,QAAQ,GAAG,SAAS,GAC5B,OAAO,CAAC,UAAU,CAAC,CAUrB;AAID,wBAAsB,SAAS,CAC7B,GAAG,EAAE,GAAG,CAAC,YAAY,CAAC,EACtB,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,QAAQ,GAAG,SAAS,GAC5B,OAAO,CAAC,SAAS,EAAE,CAAC,CAiCtB;AAID,wBAAsB,WAAW,CAC/B,GAAG,EAAE,GAAG,CAAC,YAAY,CAAC,EACtB,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,QAAQ,GAAG,SAAS,GAC5B,OAAO,CAAC,YAAY,CAAC,CAYvB;AAID,wBAAsB,WAAW,CAC/B,GAAG,EAAE,GAAG,CAAC,YAAY,CAAC,EACtB,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,QAAQ,GAAG,SAAS,EAC7B,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,YAAY,CAAC,CAkCvB;AA0CD,wBAAsB,SAAS,CAC7B,GAAG,EAAE,GAAG,CAAC,YAAY,CAAC,EACtB,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,QAAQ,GAAG,SAAS,GAC5B,OAAO,CAAC,UAAU,CAAC,CAYrB;AAID,wBAAsB,SAAS,CAC7B,GAAG,EAAE,GAAG,CAAC,YAAY,CAAC,EACtB,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,QAAQ,GAAG,SAAS,GAC5B,OAAO,CAAC,UAAU,CAAC,CAerB;AAID;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,WAAW,CAC/B,GAAG,EAAE,GAAG,CAAC,YAAY,CAAC,EACtB,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,QAAQ,GAAG,SAAS,EAC7B,OAAO,CAAC,EAAE,kBAAkB,GAC3B,OAAO,CAAC,YAAY,CAAC,CAmFvB"}
1
+ {"version":3,"file":"reads.d.ts","sourceRoot":"","sources":["../../src/dashboard/reads.ts"],"names":[],"mappings":"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"}
@@ -21,6 +21,7 @@ import { getSecurityPosture } from "../security-analytics.js";
21
21
  import { evaluateAlertConditions } from "../security-analytics.js";
22
22
  import { getAgentProfile } from "../agent-analytics.js";
23
23
  import { getSpendingBreakdown } from "../spending-analytics.js";
24
+ import { getSpendingVelocity } from "../spending-analytics.js";
24
25
  import { getVaultActivity } from "../event-analytics.js";
25
26
  import { resolveProtocolName } from "../protocol-names.js";
26
27
  /**
@@ -30,6 +31,8 @@ import { resolveProtocolName } from "../protocol-names.js";
30
31
  function asVaultState(state) {
31
32
  return state;
32
33
  }
34
+ import { SigilSdkDomainError } from "../errors/sdk.js";
35
+ import { SIGIL_ERROR__SDK__INVALID_PARAMS } from "../errors/codes.js";
33
36
  // ─── Helpers ─────────────────────────────────────────────────────────────────
34
37
  function toNet(network) {
35
38
  return network === "mainnet" ? "mainnet-beta" : "devnet";
@@ -343,7 +346,7 @@ export function buildPolicy(ctx) {
343
346
  const dailyCap = p.dailySpendingCapUsd;
344
347
  const maxPerTrade = p.maxTransactionSizeUsd ?? 0n;
345
348
  const protocolCaps = (p.protocolCaps || []);
346
- const sessionExpiry = p.sessionExpirySlots;
349
+ const sessionExpiry = p.sessionExpirySeconds;
347
350
  const policyVer = (p.policyVersion ?? 0n);
348
351
  const timelockSec = Number(p.timelockDuration);
349
352
  let pendingUpdate;
@@ -372,14 +375,12 @@ export function buildPolicy(ctx) {
372
375
  changes.protocolCaps = pp.protocolCaps.value;
373
376
  if (isSome(pp.maxSlippageBps))
374
377
  changes.maxSlippageBps = pp.maxSlippageBps.value;
375
- if (isSome(pp.maxLeverageBps))
376
- changes.leverageLimit = pp.maxLeverageBps.value;
377
378
  if (isSome(pp.allowedDestinations))
378
379
  changes.allowedDestinations = pp.allowedDestinations.value;
379
380
  if (isSome(pp.developerFeeRate))
380
381
  changes.developerFeeRate = pp.developerFeeRate.value;
381
- if (isSome(pp.sessionExpirySlots))
382
- changes.sessionExpirySlots = pp.sessionExpirySlots.value;
382
+ if (isSome(pp.sessionExpirySeconds))
383
+ changes.sessionExpirySeconds = pp.sessionExpirySeconds.value;
383
384
  if (isSome(pp.timelockDuration))
384
385
  changes.timelock = Number(pp.timelockDuration.value);
385
386
  pendingUpdate = {
@@ -397,10 +398,9 @@ export function buildPolicy(ctx) {
397
398
  hasProtocolCaps: p.hasProtocolCaps,
398
399
  protocolCaps,
399
400
  maxSlippageBps: p.maxSlippageBps,
400
- leverageLimitBps: p.maxLeverageBps,
401
401
  allowedDestinations: (p.allowedDestinations || []),
402
402
  developerFeeRate: p.developerFeeRate,
403
- sessionExpirySlots: sessionExpiry,
403
+ sessionExpirySeconds: sessionExpiry,
404
404
  timelockSeconds: timelockSec,
405
405
  policyVersion: policyVer,
406
406
  pendingUpdate,
@@ -412,10 +412,9 @@ export function buildPolicy(ctx) {
412
412
  hasProtocolCaps: p.hasProtocolCaps,
413
413
  protocolCaps: protocolCaps.map(bs),
414
414
  maxSlippageBps: p.maxSlippageBps,
415
- leverageLimitBps: p.maxLeverageBps,
416
415
  allowedDestinations: (p.allowedDestinations || []),
417
416
  developerFeeRate: p.developerFeeRate,
418
- sessionExpirySlots: bs(sessionExpiry),
417
+ sessionExpirySeconds: bs(sessionExpiry),
419
418
  timelockSeconds: timelockSec,
420
419
  policyVersion: bs(policyVer),
421
420
  pendingUpdate: pendingUpdate
@@ -727,4 +726,234 @@ export async function getOverview(rpc, vault, network, options) {
727
726
  throw toDxError(err, "OwnerClient.getOverview");
728
727
  }
729
728
  }
729
+ // ─── getAgentDetail (S10) ────────────────────────────────────────────────────
730
+ /**
731
+ * Compose a single {@link AgentData} from a pre-fetched {@link OverviewContext}.
732
+ *
733
+ * Reuses {@link buildAgents} and filters to the requested address. Returns
734
+ * `null` when the agent is not registered in the vault — callers that want
735
+ * the throwing surface use `getAgentDetail` instead.
736
+ *
737
+ * Activity-derived fields (`lastActionType` / `lastActionProtocol` /
738
+ * `lastActionTimestamp` / `blockedCount24h`) follow the same defaulting rules
739
+ * as `buildAgents`: empty/zero when `ctx.activity` is undefined.
740
+ *
741
+ * @experimental Part of the `build*` composition surface (S10). Signature and
742
+ * JSON shape may shift before v1.0.
743
+ *
744
+ * @see OwnerClient.getAgentDetail — the stable single-call alternative.
745
+ */
746
+ export function buildAgentDetail(ctx, agent) {
747
+ const all = buildAgents(ctx);
748
+ return all.find((a) => a.address === agent) ?? null;
749
+ }
750
+ /**
751
+ * Single-agent detail wrapper around {@link getAgentProfile} + activity
752
+ * enrichment. Resolves vault state, fetches the same 100-event activity
753
+ * window as `getAgents`, and returns the {@link AgentData} for the requested
754
+ * agent.
755
+ *
756
+ * Throws a typed {@link SigilSdkDomainError} (mapped through `toDxError` to
757
+ * `SIGIL_ERROR__SDK__INVALID_PARAMS`) when the agent is not registered in
758
+ * the vault. Same graceful-degradation pattern as `getAgents` for activity
759
+ * fetch failures: enrichment fields default to empty/zero rather than
760
+ * propagating the failure.
761
+ */
762
+ export async function getAgentDetail(rpc, vault, agent, network) {
763
+ try {
764
+ const [state, activity] = await Promise.all([
765
+ resolveVaultStateForOwner(rpc, vault, undefined, toNet(network)),
766
+ getVaultActivity(rpc, vault, 100, toNet(network)).catch((err) => {
767
+ // Same redaction discipline as getAgents (PR 1.B).
768
+ const cause = redactCause(err);
769
+ getSigilModuleLogger().warn("[OwnerClient.getAgentDetail] activity enrichment failed — falling back to empty last-action fields", { cause: cause.message ?? cause.name ?? cause.code ?? "unknown" });
770
+ return [];
771
+ }),
772
+ ]);
773
+ const detail = buildAgentDetail({ vault, state, activity }, agent);
774
+ if (!detail) {
775
+ throw new SigilSdkDomainError(SIGIL_ERROR__SDK__INVALID_PARAMS, `Agent ${agent} is not registered in vault ${vault}`, { context: { field: "agent", received: agent } });
776
+ }
777
+ return detail;
778
+ }
779
+ catch (err) {
780
+ throw toDxError(err, "OwnerClient.getAgentDetail");
781
+ }
782
+ }
783
+ // ─── getRiskMetrics (S11) ────────────────────────────────────────────────────
784
+ /**
785
+ * Map an {@link Alert}[] to the four-level UI risk badge. Critical wins over
786
+ * warning, warning wins over info; absence of any alerts is "low".
787
+ *
788
+ * Pure helper — exposed for direct testing. Most consumers use
789
+ * {@link getRiskMetrics}.
790
+ */
791
+ export function deriveRiskLevel(alerts) {
792
+ let hasWarning = false;
793
+ let hasInfo = false;
794
+ for (const a of alerts) {
795
+ if (a.severity === "critical")
796
+ return "critical";
797
+ if (a.severity === "warning")
798
+ hasWarning = true;
799
+ else if (a.severity === "info")
800
+ hasInfo = true;
801
+ }
802
+ if (hasWarning)
803
+ return "high";
804
+ if (hasInfo)
805
+ return "elevated";
806
+ return "low";
807
+ }
808
+ /**
809
+ * Compute {@link RiskMetrics} from a pre-fetched {@link OverviewContext}.
810
+ *
811
+ * Combines:
812
+ * - {@link getSpendingVelocity}(state.tracker, now, state.globalBudget) →
813
+ * `currentRate` becomes `spendingVelocity`; `isAccelerating` and
814
+ * `timeToCapSeconds` flow through directly.
815
+ * - 24h cap projection → `capVelocity = currentRate * 24 / cap × 100`
816
+ * (clamped at 0 when cap is 0n).
817
+ * - {@link evaluateAlertConditions}(state, vault) → `riskLevel` via
818
+ * {@link deriveRiskLevel}. Uses `ctx.alerts` when memoized.
819
+ *
820
+ * @experimental Part of the `build*` composition surface (S11). Signature and
821
+ * JSON shape may shift before v1.0.
822
+ *
823
+ * @see OwnerClient.getRiskMetrics — the stable single-call alternative.
824
+ */
825
+ export function buildRiskMetrics(ctx) {
826
+ const state = ctx.state;
827
+ const nowUnix = BigInt(Math.floor(Date.now() / 1000));
828
+ const velocity = getSpendingVelocity(state.tracker, nowUnix, state.globalBudget);
829
+ const alerts = ctx.alerts ?? evaluateAlertConditions(state, ctx.vault);
830
+ // capVelocity: percent of daily cap consumed in 24h at current rate.
831
+ // 0 when cap is unset (matches alert logic which only fires on cap > 0).
832
+ const cap = state.globalBudget.cap;
833
+ let capVelocity = 0;
834
+ if (cap > 0n && velocity.currentRate > 0n) {
835
+ // Promote to Number for the percent calc — rate × 24 / cap × 100.
836
+ // currentRate is hourly USD base units; cap is total USD base units.
837
+ capVelocity = (Number(velocity.currentRate * 24n) / Number(cap)) * 100;
838
+ }
839
+ const riskLevel = deriveRiskLevel(alerts);
840
+ const spendingVelocity = velocity.currentRate;
841
+ const isAccelerating = velocity.isAccelerating;
842
+ const timeToCapSeconds = velocity.timeToCapSeconds;
843
+ return {
844
+ capVelocity,
845
+ spendingVelocity,
846
+ riskLevel,
847
+ isAccelerating,
848
+ timeToCapSeconds,
849
+ toJSON: () => ({
850
+ capVelocity,
851
+ spendingVelocity: bs(spendingVelocity),
852
+ riskLevel,
853
+ isAccelerating,
854
+ timeToCapSeconds,
855
+ }),
856
+ };
857
+ }
858
+ /**
859
+ * Risk-tilt summary for a vault — current spending velocity, daily-cap
860
+ * projection, and a four-level risk badge derived from the alert stream.
861
+ *
862
+ * One state resolution + one alert evaluation. Use this for the dashboard's
863
+ * "is something concerning right now?" indicator. For deeper inspection,
864
+ * pair with `getOverview` (which embeds the alert list) or the
865
+ * `evaluateAlertConditions` export.
866
+ */
867
+ export async function getRiskMetrics(rpc, vault, network) {
868
+ try {
869
+ const state = await resolveVaultStateForOwner(rpc, vault, undefined, toNet(network));
870
+ return buildRiskMetrics({ vault, state });
871
+ }
872
+ catch (err) {
873
+ throw toDxError(err, "OwnerClient.getRiskMetrics");
874
+ }
875
+ }
876
+ // ─── getAuditTrail (S12) ─────────────────────────────────────────────────────
877
+ /**
878
+ * Categories from {@link getVaultActivity} that count as audit events.
879
+ *
880
+ * Trades, deposits, withdrawals, and fee accruals are routine operating
881
+ * activity and are excluded. Constraint changes ride alongside policy
882
+ * changes (the underlying decoder maps them all to `policy`), so they are
883
+ * captured under `policy_change`.
884
+ */
885
+ const AUDIT_CATEGORY_TO_TYPE = {
886
+ policy: "policy_change",
887
+ agent: "agent_change",
888
+ security: "vault_security",
889
+ escrow: "escrow",
890
+ };
891
+ /**
892
+ * Filter raw {@link VaultActivityItem}[] to the audit subset and map each to
893
+ * an {@link AuditTrailEntry}. Pure — no RPC, no time-based filtering.
894
+ *
895
+ * Used by both `getAuditTrail` (which then applies the optional `since`
896
+ * timestamp filter) and direct callers that already have an activity list.
897
+ *
898
+ * @experimental Part of the `build*` composition surface (S12).
899
+ */
900
+ export function buildAuditTrail(items) {
901
+ const out = [];
902
+ for (const item of items) {
903
+ const eventType = AUDIT_CATEGORY_TO_TYPE[item.category];
904
+ if (!eventType)
905
+ continue;
906
+ const timestamp = item.timestamp * 1000;
907
+ const eventName = item.eventType ?? "";
908
+ const actor = item.agent || "";
909
+ const details = item.description;
910
+ const txSignature = item.txSignature;
911
+ out.push({
912
+ timestamp,
913
+ eventType,
914
+ eventName,
915
+ actor,
916
+ details,
917
+ txSignature,
918
+ toJSON: () => ({
919
+ timestamp,
920
+ eventType,
921
+ eventName,
922
+ actor,
923
+ details,
924
+ txSignature,
925
+ }),
926
+ });
927
+ }
928
+ return out;
929
+ }
930
+ /**
931
+ * Governance + security audit trail — the policy/agent/security/escrow
932
+ * subset of the vault's activity stream.
933
+ *
934
+ * Use this for an admin-facing "what changed?" feed: policy queue/apply
935
+ * cycles, agent registrations, vault freeze/resume events, and escrow
936
+ * lifecycle. Trades and fund movements are excluded — they live in
937
+ * `getActivity()`.
938
+ *
939
+ * Activity fetch shape: one `getSignaturesForAddress` + up to `limit`
940
+ * sequential `getTransaction` calls (see {@link getVaultActivity}).
941
+ * Default limit is 100 — large enough to surface a few weeks of governance
942
+ * activity for a typical vault without inflating RPC cost.
943
+ */
944
+ export async function getAuditTrail(rpc, vault, network, opts) {
945
+ try {
946
+ const limit = opts?.limit ?? 100;
947
+ const items = await getVaultActivity(rpc, vault, limit, toNet(network));
948
+ let entries = buildAuditTrail(items);
949
+ if (opts?.since !== undefined) {
950
+ const since = opts.since;
951
+ entries = entries.filter((e) => e.timestamp >= since);
952
+ }
953
+ return entries;
954
+ }
955
+ catch (err) {
956
+ throw toDxError(err, "OwnerClient.getAuditTrail");
957
+ }
958
+ }
730
959
  //# sourceMappingURL=reads.js.map