@engramx/idl 0.16.0-rc.2 → 0.16.0-rc.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/market.did CHANGED
@@ -81,6 +81,7 @@ type SessionCounts =
81
81
  closing: nat;
82
82
  expired: nat;
83
83
  open: nat;
84
+ refundOwed: opt nat;
84
85
  total: nat;
85
86
  };
86
87
  type SessionConfig =
@@ -127,6 +128,12 @@ type SellerStatus =
127
128
  expiresAtNs: int;
128
129
  verifiedAtNs: int;
129
130
  };
131
+ type SealedEntry =
132
+ record {
133
+ digest: blob;
134
+ entryHash: blob;
135
+ id: nat;
136
+ };
130
137
  type RoleGrant =
131
138
  record {
132
139
  holder: principal;
@@ -171,87 +178,97 @@ type RevenueSummary =
171
178
  type Result_9 =
172
179
  variant {
173
180
  Err: Error;
174
- Ok: Page_7;
181
+ Ok: Page_5;
175
182
  };
176
183
  type Result_8 =
177
184
  variant {
178
185
  Err: Error;
179
- Ok: Page_5;
186
+ Ok: Page_4;
180
187
  };
181
188
  type Result_7 =
182
189
  variant {
183
190
  Err: Error;
184
- Ok: Page_4;
191
+ Ok: Page_2;
185
192
  };
186
193
  type Result_6 =
187
194
  variant {
188
195
  Err: Error;
189
- Ok: Page_2;
196
+ Ok: Page_1;
190
197
  };
191
198
  type Result_5 =
192
199
  variant {
193
200
  Err: Error;
194
- Ok: Page_1;
201
+ Ok: SessionState;
195
202
  };
196
203
  type Result_4 =
197
204
  variant {
198
205
  Err: Error;
199
- Ok: SessionState;
206
+ Ok: PaymentQuote;
200
207
  };
201
208
  type Result_3 =
202
209
  variant {
203
210
  Err: Error;
204
- Ok: PaymentQuote;
211
+ Ok: EscrowRecovery;
212
+ };
213
+ type Result_20 =
214
+ variant {
215
+ Err: Error;
216
+ Ok: X402Endpoint;
205
217
  };
206
218
  type Result_2 =
207
219
  variant {
208
220
  Err: Error;
209
221
  Ok: text;
210
222
  };
223
+ type Result_19 =
224
+ variant {
225
+ Err: Error;
226
+ Ok: ServiceRequestResponse;
227
+ };
211
228
  type Result_18 =
212
229
  variant {
213
230
  Err: Error;
214
- Ok: X402Endpoint;
231
+ Ok: ContentResponse;
215
232
  };
216
233
  type Result_17 =
217
234
  variant {
218
235
  Err: Error;
219
- Ok: ServiceRequestResponse;
236
+ Ok: opt text;
220
237
  };
221
238
  type Result_16 =
222
239
  variant {
223
240
  Err: Error;
224
- Ok: ContentResponse;
241
+ Ok: Job;
225
242
  };
226
243
  type Result_15 =
227
244
  variant {
228
245
  Err: Error;
229
- Ok: opt text;
246
+ Ok: blob;
230
247
  };
231
248
  type Result_14 =
232
249
  variant {
233
250
  Err: Error;
234
- Ok: Job;
251
+ Ok: JobStatus;
235
252
  };
236
253
  type Result_13 =
237
254
  variant {
238
255
  Err: Error;
239
- Ok: blob;
256
+ Ok: RevenueSummary;
240
257
  };
241
258
  type Result_12 =
242
259
  variant {
243
260
  Err: Error;
244
- Ok: JobStatus;
261
+ Ok: SellerStatus;
245
262
  };
246
263
  type Result_11 =
247
264
  variant {
248
265
  Err: Error;
249
- Ok: RevenueSummary;
266
+ Ok: RecordPage;
250
267
  };
251
268
  type Result_10 =
252
269
  variant {
253
270
  Err: Error;
254
- Ok: SellerStatus;
271
+ Ok: Page_7;
255
272
  };
256
273
  type Result_1 =
257
274
  variant {
@@ -263,6 +280,14 @@ type Result =
263
280
  Err: Error;
264
281
  Ok: nat;
265
282
  };
283
+ type RecordPage =
284
+ record {
285
+ hashFirstFrom: nat;
286
+ items: vec AuditEntry;
287
+ ringFloor: nat;
288
+ sealed: vec SealedEntry;
289
+ total: nat;
290
+ };
266
291
  type QuotedRequirement =
267
292
  record {
268
293
  amount: nat;
@@ -466,6 +491,11 @@ type GenesisNote =
466
491
  predecessorSize: opt nat;
467
492
  version: text;
468
493
  };
494
+ type EscrowRecovery =
495
+ record {
496
+ amount: TokenAmount;
497
+ blockIndex: nat;
498
+ };
469
499
  type Error =
470
500
  variant {
471
501
  Conflict: text;
@@ -616,6 +646,9 @@ service : {
616
646
  /// is RATIFIED as the 0.16.0 contract (the owner's ruling of 2026-10-02, the pre-cut
617
647
  /// recommendation); giving the library one arm per kind of refusal is post-cut dependency work,
618
648
  /// not a change made mid-cut.
649
+ /// ⟨2026-10-07, beside the count above⟩ Twelve: the admin's `retrySellerPayment` (the owner's
650
+ /// decision of that day) passes the library's settle refusal through as `#Conflict` too — state
651
+ /// behind this canister's own gate, like the other six.
619
652
  ///
620
653
  /// It also refuses while TRADE IS FROZEN, and that one is a true `#Conflict` — the refusal says
621
654
  /// so explicitly ("Not a permission problem and not a missing job"), and `isTradeFrozen()` is the
@@ -649,7 +682,7 @@ service : {
649
682
  /// Born disabled deliberately: a listing that went live at creation would be sellable before its
650
683
  /// price was set, and `price` starts at 0 with `suggestedPrice` as the fallback.
651
684
  createEndpoint: (name: text, description: text, contentId: text,
652
- suggestedPriceE6: nat) -> (Result_18);
685
+ suggestedPriceE6: nat) -> (Result_20);
653
686
  /// Submit a paid service request. Returns a job id, or the price.
654
687
  ///
655
688
  /// ⟨0.16.0⟩ TWO GATES FROM THE ENGRAM DO NOT TRAVEL, and both for the same reason: they were the
@@ -664,7 +697,7 @@ service : {
664
697
  ///
665
698
  /// What DOES gate here is the market's freeze, and the service's own existence and pricing mode.
666
699
  createJob: (serviceId: text, params: blob, paymentSig:
667
- opt PaymentSignature) -> (Result_17);
700
+ opt PaymentSignature) -> (Result_19);
668
701
  /// Delete content.
669
702
  ///
670
703
  /// ⚠ THE QUOTA IS NOT REFUNDED, and this is the honest part of the design rather than a
@@ -753,7 +786,7 @@ service : {
753
786
  /// before the nonce lock or any ledger call, and the refusal reaches the buyer as #Refused with
754
787
  /// ic402's text naming both principals. Pay as the principal that approved the allowance.
755
788
  getContent: (contentId: text, paymentSig: opt PaymentSignature) ->
756
- (Result_16);
789
+ (Result_18);
757
790
  /// ⟨0.16.0⟩ THE `getChunk` FIX, and it is the sharpest single case in the corpus.
758
791
  ///
759
792
  /// The engram's version was:
@@ -778,13 +811,13 @@ service : {
778
811
  /// list they scan holds authorization helpers only — so a refusal fabricated behind a payment
779
812
  /// check was out of scope by construction rather than by ruling. L11 adds payment gates to that
780
813
  /// list; this method is why.
781
- getContentChunk: (grant: AccessGrant, index: nat) -> (Result_13) query;
814
+ getContentChunk: (grant: AccessGrant, index: nat) -> (Result_15) query;
782
815
  /// A seller's payout address — THEIRS, or the admin's to read.
783
816
  ///
784
817
  /// The engram made this owner-only and TRAPPED at everyone else. Here the answer is a refusal a
785
818
  /// caller can read, and `#Ok(null)` genuinely means "this seller has set no payout address" —
786
819
  /// distinguishable from "you may not ask", which is the whole point of the envelope.
787
- getEvmSellerPayout: (seller: principal) -> (Result_15) query;
820
+ getEvmSellerPayout: (seller: principal) -> (Result_17) query;
788
821
  /// PUBLIC: what this canister's chains continue, or that they continue nothing. A fresh chain
789
822
  /// beside a published predecessor head is auditable; a fresh chain with no statement is
790
823
  /// indistinguishable from a wipe.
@@ -797,7 +830,7 @@ service : {
797
830
  /// collapsed "unknown jobId" and "not authorized", and the product rendered the wrong conclusion
798
831
  /// from it — the marketplace UI printed "Job not found (or not yet visible)" at a caller who was
799
832
  /// merely unauthorized. Job existence is not the secret: `getJobCounts()` is ungated.
800
- getJob: (jobId: text) -> (Result_14) query;
833
+ getJob: (jobId: text) -> (Result_16) query;
801
834
  /// PUBLIC: aggregate counts that identify nobody — and already public on the engram, which is
802
835
  /// what made `listJobs`' existence-leak justification false.
803
836
  getJobCounts: () -> (JobCounts) query;
@@ -810,7 +843,7 @@ service : {
810
843
  ///
811
844
  /// Three outcomes, three answers now. And `Payer` (above) removes the root cause rather than
812
845
  /// only labelling it.
813
- getJobResult: (jobId: text) -> (Result_13) query;
846
+ getJobResult: (jobId: text) -> (Result_15) query;
814
847
  /// Terminal money settlement — the seller gets paid. Honours the freeze exactly like every
815
848
  /// other settle path; a settlement that ignored the freeze would make the freeze a suggestion.
816
849
  /// PUBLIC: a job's state, and nothing else about it.
@@ -825,7 +858,7 @@ service : {
825
858
  ///
826
859
  /// The engram returned `?EngramJobStatus`, conflating "no such job" with a null-ish answer. Here
827
860
  /// a missing job is `#NotFound`, which is a fact rather than an absence a caller has to interpret.
828
- getJobStatus: (jobId: text) -> (Result_12) query;
861
+ getJobStatus: (jobId: text) -> (Result_14) query;
829
862
  /// PUBLIC: the market's spend limits, with the caller rosters REDACTED.
830
863
  ///
831
864
  /// The limits themselves are already public — they are advertised inside every 402 challenge, so
@@ -848,7 +881,7 @@ service : {
848
881
  /// Anonymous is refused rather than answered with zeroes. A zero here is a real business fact —
849
882
  /// "you have sold nothing" — and returning it to a caller who simply has no identity is the
850
883
  /// fabricated-empty defect wearing a number instead of a list.
851
- getRevenueSummary: () -> (Result_11) query;
884
+ getRevenueSummary: () -> (Result_13) query;
852
885
  /// PUBLIC: what a buyer can learn about a seller, and the whole of it.
853
886
  ///
854
887
  /// The ENGRAM ID is the point of this read. This market runs no reputation system and issues no
@@ -859,7 +892,7 @@ service : {
859
892
  ///
860
893
  /// `verified` is about ownership at a moment in time and nothing else. It is not an endorsement,
861
894
  /// and the field name is the strongest claim it makes.
862
- getSellerStatus: (seller: principal) -> (Result_10) query;
895
+ getSellerStatus: (seller: principal) -> (Result_12) query;
863
896
  /// PUBLIC: aggregate session counts. Identifies nobody, and the same reasoning as getJobCounts —
864
897
  /// which is also what made `listJobs`' old "no existence leak" defence false.
865
898
  getSessionCounts: () -> (SessionCounts) query;
@@ -938,17 +971,23 @@ service : {
938
971
  isTradeFrozen: () -> (bool) query;
939
972
  /// `total` is the head counter, not the row count: this is a bounded ring, so a page that
940
973
  /// reported only what it returned would make a trimmed log look complete.
941
- listAuditEntries: (start: nat, limit: nat) -> (Result_8) query;
974
+ ///
975
+ /// ⟨2026-10-15, the owner's ruling 6B of 2026-10-14⟩ The reply is the shared `Wire.RecordPage`, so
976
+ /// one checker reads every chain. A viewer sees every entry, so `sealed` is always empty here;
977
+ /// `ringFloor` says where the ring starts and `hashFirstFrom` where this record switched to the
978
+ /// hash-first rule. The gate is unchanged (hash-only rows for strangers were ruled for the
979
+ /// engram's record).
980
+ listAuditEntries: (start: nat, limit: nat) -> (Result_11) query;
942
981
  /// Admin AND the enrolled viewers themselves — L8's roster rule. A viewer who cannot see the
943
982
  /// roster cannot tell whether their own enrolment survived a rotation.
944
- listAuditViewers: () -> (Result_9) query;
983
+ listAuditViewers: () -> (Result_10) query;
945
984
  /// PUBLIC: the catalogue is the storefront. A shop that refuses to say what it sells to
946
985
  /// anyone who has not already bought is not a shop.
947
986
  listContent: (start: nat, limit: nat) -> (Page_6) query;
948
987
  /// L11 names this canister's reason for having a denial log at all: the commerce surface is where
949
988
  /// the fabricated-empty class was born, and a refusal that leaves no trace cannot be counted,
950
989
  /// alerted on, or disproved.
951
- listDenialEntries: (start: nat, limit: nat) -> (Result_8) query;
990
+ listDenialEntries: (start: nat, limit: nat) -> (Result_9) query;
952
991
  /// Purchase history for one endpoint: its creator sees every row, a buyer sees their own.
953
992
  ///
954
993
  /// ⟨0.16.0⟩ Two defects close here at once, and they are the same defect wearing two hats.
@@ -962,7 +1001,7 @@ service : {
962
1001
  /// few sales. `withheld` now counts them, so "no purchases here" and "not yours to see" are
963
1002
  /// different answers — without naming whose they were.
964
1003
  listEndpointPurchases: (endpointId: text, start: nat, limit: nat) ->
965
- (Result_7) query;
1004
+ (Result_8) query;
966
1005
  /// PUBLIC: the shelves, like the catalogue. `#Deleted` listings are excluded from an
967
1006
  /// unfiltered read and COUNTED in `withheld` — a shop with three deleted listings and a shop with
968
1007
  /// none look different, which is the honest answer, without publishing what was withdrawn.
@@ -990,7 +1029,7 @@ service : {
990
1029
  /// Now: `#Refused` when the caller may not ask, `#NotFound` when the service does not exist —
991
1030
  /// two facts that were one empty list.
992
1031
  listJobs: (serviceId: text, statusFilter: opt JobStatus, start: nat, limit:
993
- nat) -> (Result_6) query;
1032
+ nat) -> (Result_7) query;
994
1033
  /// The parked withdrawals belonging to this caller, so an unresolved payout is discoverable
995
1034
  /// rather than something a seller has to already know the id of.
996
1035
  ///
@@ -1005,7 +1044,7 @@ service : {
1005
1044
  /// not see, so nothing is ever hidden from them — unlike `listEndpointPurchases`, where a
1006
1045
  /// non-owner's view withholds other buyers' rows. Stated because a reader comparing the two
1007
1046
  /// should know the zero is a fact about this surface, not an unimplemented field.
1008
- listMyPendingWithdrawals: (start: nat, limit: nat) -> (Result_5) query;
1047
+ listMyPendingWithdrawals: (start: nat, limit: nat) -> (Result_6) query;
1009
1048
  /// ⟨0.16.0⟩ `listAllServices` FOLDS in as `includeDisabled`.
1010
1049
  ///
1011
1050
  /// The engram had two methods because the visibility rule differed: everyone saw enabled
@@ -1055,7 +1094,7 @@ service : {
1055
1094
  /// ⟨2026-09-30, ic402 2.17.0⟩ That future spend path calls `gate.consumeVoucherFrom(msg.caller, …)`,
1056
1095
  /// not the bare `consumeVoucher`: the signed fallback is off on this canister, so the bare call
1057
1096
  /// refuses every voucher, and only the session key calling as itself may spend a session.
1058
- openSession: (config: SessionConfig, sig: PaymentSignature) -> (Result_4);
1097
+ openSession: (config: SessionConfig, sig: PaymentSignature) -> (Result_5);
1059
1098
  /// RENAMED from `requestSession` (census tier-3 #21): it is a pure dry run — a quote for a session
1060
1099
  /// the caller has not opened and is not committed to. `request` read as an action with an effect.
1061
1100
  ///
@@ -1117,7 +1156,7 @@ service : {
1117
1156
  /// This matters most on the ckUSDC rail, which is where customer payments settle: ICP has no
1118
1157
  /// on-chain nonce, so `settle` ALWAYS requires the server one. A conformant EVM x402 client
1119
1158
  /// sends no server nonce at all and is unaffected.
1120
- quotePayment: (amountE6: nat) -> (Result_3) query;
1159
+ quotePayment: (amountE6: nat) -> (Result_4) query;
1121
1160
  /// Admin recovery: re-drive a job stuck mid-settlement — a broadcast EVM transfer whose outcome
1122
1161
  /// this canister never learned. Reads the chain and finishes what the settle started.
1123
1162
  ///
@@ -1196,7 +1235,15 @@ service : {
1196
1235
  /// refused or rejected: that close already ends the session `closed`, with the remainder still in
1197
1236
  /// its escrow, so it needs no force. Recover it within 24 hours of that close, asking at most the
1198
1237
  /// escrow's ledger balance less one fee.
1199
- recoverEscrow: (sessionId: text, amount: TokenAmount) -> (Result);
1238
+ ///
1239
+ /// ⟨2026-10-07, the owner's decision of that day⟩ WHAT IT ANSWERS: what came back. `amount` is what
1240
+ /// was transferred to the session's payer, in the token named (the amount asked, capped at the
1241
+ /// session's unconsumed deposit; the transfer's fee comes out of the escrow on top), and
1242
+ /// `blockIndex` is that ledger's block of the transfer. Until this date it answered a bare `nat`
1243
+ /// that was the block index alone, which read as the amount. If the session's record is removed
1244
+ /// before the amount can be read back — a session closed in the same moment as the recovery and
1245
+ /// cleaned up during its transfer — it answers `#Other` naming the block, never a guessed amount.
1246
+ recoverEscrow: (sessionId: text, amount: TokenAmount) -> (Result_3);
1200
1247
  /// Register as a seller by naming the engram you own.
1201
1248
  ///
1202
1249
  /// The registry is asked, not trusted from the caller's word: `verifyEngramActiveOwner` confirms
@@ -1284,6 +1331,36 @@ service : {
1284
1331
  /// contract as ratified on 2026-10-02; giving the library one arm per kind of refusal is post-cut
1285
1332
  /// dependency work.
1286
1333
  resolveJob: (jobId: text, terminal: JobStatus) -> (Result_1);
1334
+ /// Admin recovery: retry the payment to the seller of a job left `#Verified` by a failed payment.
1335
+ /// NOTHING ELSE. It never refunds the buyer, and it refuses every job that does not read
1336
+ /// `#Verified`, with nothing moved.
1337
+ ///
1338
+ /// ⟨2026-10-07, the owner's decision of that day⟩ A job whose work passed verification and whose
1339
+ /// payment to the seller then failed rests in `#Verified`, and only `resolveDispute` moves it — the
1340
+ /// service's SELLER's, by the ruling of 2026-08-17, which stands unchanged. A seller who never acts
1341
+ /// left it there, with no way for anyone else to move it. This is the admin's way: unstick, not
1342
+ /// decide. The job's outcome was decided by its verification; the payment goes where that sent it,
1343
+ /// and the admin names neither a recipient nor an amount. Refunding the buyer, and anything about a
1344
+ /// job not yet verified (`#Submitted`, `#Disputed`), stay the seller's.
1345
+ ///
1346
+ /// It runs the library's own settle, the one a buyer's confirmation runs: the job reads `#Settling`
1347
+ /// while it pays (so two retries cannot both pay), ends `#Settled`, and a payment the ledger refuses
1348
+ /// leaves it `#Verified` to retry again. For a job priced "up to" an amount, that settle also returns
1349
+ /// to the buyer what the seller did not claim, as every settle does. Past the admin check, the
1350
+ /// freeze and the cycles floor (each of which refuses before anything is read), every outcome is a
1351
+ /// chained record entry naming the admin.
1352
+ ///
1353
+ /// A NEW METHOD, NOT A WIDER `resolveJob`, ON PURPOSE. `resolveJob` is the one place the admin line
1354
+ /// bends — a STATE assertion, moving no money, for a job stuck in `#Settling`. Widening it to move
1355
+ /// money on a `#Verified` job would give one argument (`#Settled`) two meanings depending on a state
1356
+ /// the admin read a moment earlier: if the job moved to `#Settling` in between (a settle in flight),
1357
+ /// "pay the seller" would become "declare the seller paid". One method per meaning keeps the
1358
+ /// deciding one narrow and named.
1359
+ ///
1360
+ /// `#Conflict` covers the state refusals: a job that does not read `#Verified`, and the library's
1361
+ /// own (a job that moved on before the retry ran, or a payment that failed). `#NotFound` is a job id
1362
+ /// this market does not have.
1363
+ retrySellerPayment: (jobId: text) -> (Result_1);
1287
1364
  setAdmin: (newAdmin: principal) -> (Result_1);
1288
1365
  /// Override the policy for ONE payer — the market's per-buyer risk control.
1289
1366
  setCallerPolicy: (caller: principal, policy: SpendingPolicy) -> (Result_1);