@wirecat/cli-core 0.571.0 → 0.573.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.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,24 @@ shape of this file.
7
7
 
8
8
  ## Unreleased
9
9
 
10
+ ## 0.573.0 — 05.11.2026
11
+
12
+ ### Added
13
+
14
+ - **The owner sets a confirmed payment's wrong split right.** `store.finance.unallocate` now takes an allocation back
15
+ from a confirmed payment too, when `by` is the owner; `allocate` then puts the right amounts on, under the same
16
+ over-payment, over-invoice and currency rules, and the invoices' statuses follow. A bot is still refused on a
17
+ confirmed payment (`finance.owner-only`); a rejected or deleted payment is `finance.unallocate`.
18
+
19
+ ## 0.572.0 — 05.11.2026
20
+
21
+ ### Changed — may break callers
22
+
23
+ - **`facts.unconfirm` is now `facts.revoke`**, its refusal reason `fact.unconfirm-correction` is
24
+ `fact.revoke-correction`, and the step it writes into a fact's `metadata.history` is `revoked`. memo's command is
25
+ `memo facts revoke`, a word the shared vocabulary has ("take back what was granted"); `unconfirm` is not in it. Nothing
26
+ called the old names but memo's unreleased command, which moves with this.
27
+
10
28
  ## 0.571.0 — 05.11.2026
11
29
 
12
30
  ### Added
@@ -164,10 +164,10 @@ const OTHERS = [
164
164
  validation("input.required", "the command needs an answer and cannot ask for one"),
165
165
  validation("input.too-large", "the input is over its size limit"),
166
166
  ["meeting-project.stale", "configuration_error", "the meeting's project changed meanwhile"],
167
- validation("fact.not-accepted", "only an accepted fact can be unconfirmed"),
168
- validation("fact.owner-written", "the owner wrote this fact; it was never proposed, so it cannot be unconfirmed"),
167
+ validation("fact.not-accepted", "only an accepted fact can be revoked"),
168
+ validation("fact.owner-written", "the owner wrote this fact; it was never proposed, so it cannot be revoked"),
169
169
  validation("fact.payment-retired", "a payment is a payments row in store.finance, not a fact"),
170
- validation("fact.unconfirm-correction", "an accepted correction cannot be unconfirmed; its superseded fact stays"),
170
+ validation("fact.revoke-correction", "an accepted correction cannot be revoked; its superseded fact stays"),
171
171
  validation("finance.allocate", "the invoice or payment cannot take an allocation in its state"),
172
172
  validation("finance.currency", "the payment and the invoice are in different currencies; nothing is converted"),
173
173
  validation("finance.field", "a field of the invoice or payment is not valid"),
@@ -181,7 +181,7 @@ const OTHERS = [
181
181
  validation("finance.ref", "the reference names no invoice or payment"),
182
182
  validation("finance.status", "the invoice's status does not allow this"),
183
183
  validation("finance.total", "the invoice's total is not the sum of its lines"),
184
- validation("finance.unallocate", "only a proposed payment's allocations are taken back"),
184
+ validation("finance.unallocate", "a rejected or deleted payment's allocations are not taken back"),
185
185
  validation("record.entity", "the invoice or payment the record stands for was refused"),
186
186
  ["record.map-owner-only", "permission_error", "only the owner says which entity a source record is"],
187
187
  validation("record.map-type", "a record maps only to an entity of its own type"),
@@ -74,7 +74,7 @@ export interface FactsStore {
74
74
  * The owner takes back the approval of an accepted fact an agent proposed: it waits as `proposed` again. The step is
75
75
  * kept in `metadata.history`, with the decision it took back.
76
76
  */
77
- unconfirm(reference: string, by: Decider, reason?: string): Promise<Fact>;
77
+ revoke(reference: string, by: Decider, reason?: string): Promise<Fact>;
78
78
  /** The owner, or an agent for the owner, turns down a proposed fact; it stays, marked `rejected`. */
79
79
  reject(reference: string, by: Decider, reason?: string): Promise<Fact>;
80
80
  /**
@@ -154,24 +154,24 @@ export const factOperationsOver = (context) => {
154
154
  database.prepare("UPDATE facts SET status = 'reversed', updated_at = ? WHERE id = ?").run(now(), Number(row.id));
155
155
  return factOf(rowOf(reference));
156
156
  },
157
- unconfirm: (reference, by, reason) => {
157
+ revoke: (reference, by, reason) => {
158
158
  const row = rowOf(reference);
159
159
  const ref = `fact:${row.id}`;
160
160
  assertMayWithdraw({ id: ref, proposedBy: { type: "unknown" }, proposed: false }, by);
161
161
  write(database, () => {
162
162
  const current = database.prepare("SELECT * FROM facts WHERE id = ?").get(Number(row.id));
163
163
  if (current.status !== "accepted")
164
- throw new CliError("validation_error", `only an accepted fact can be unconfirmed; ${ref} is ${String(current.status)}`, { reason: "fact.not-accepted" });
164
+ throw new CliError("validation_error", `only an accepted fact can be revoked; ${ref} is ${String(current.status)}`, { reason: "fact.not-accepted" });
165
165
  if (current.author_type === "person")
166
166
  throw new CliError("validation_error", `${ref} is the owner's own fact, never proposed; correct it with a fact that supersedes it, or remove it`, { reason: "fact.owner-written" });
167
167
  // Accepting it marked the fact it corrects superseded, and what that one was before is not kept.
168
168
  if (current.supersedes_id != null)
169
169
  throw new CliError("validation_error", `${ref} corrects fact:${current.supersedes_id}, which stopped holding when ${ref} was accepted; ` +
170
- "remove it or correct it with another fact instead", { reason: "fact.unconfirm-correction" });
170
+ "remove it or correct it with another fact instead", { reason: "fact.revoke-correction" });
171
171
  const at = now();
172
172
  const { decision, history, ...metadata } = (current.metadata == null ? {} : JSON.parse(String(current.metadata)));
173
173
  const step = {
174
- step: "unconfirmed",
174
+ step: "revoked",
175
175
  by: "owner",
176
176
  at: iso(at),
177
177
  confirmedBy: { type: current.confirmed_by_type, id: String(current.confirmed_by_id) },
@@ -236,7 +236,7 @@ export const factsStoreOver = (context) => {
236
236
  list: async (options) => operations.list(options),
237
237
  accept: async (reference, by, reason) => operations.accept(reference, by, reason),
238
238
  reverse: async (reference, by) => operations.reverse(reference, by),
239
- unconfirm: async (reference, by, reason) => operations.unconfirm(reference, by, reason),
239
+ revoke: async (reference, by, reason) => operations.revoke(reference, by, reason),
240
240
  reject: async (reference, by, reason) => operations.reject(reference, by, reason),
241
241
  remove: async (reference, by) => operations.remove(reference, by),
242
242
  sources: async (reference) => operations.sources(reference),
@@ -181,8 +181,8 @@ export interface FinanceStore {
181
181
  by: Author;
182
182
  }): Promise<Allocation>;
183
183
  /**
184
- * Takes one allocation back from a payment still proposed, under the same rule as `allocate`. A confirmed payment's
185
- * allocations are decided money and stay.
184
+ * Takes one allocation back, under the same rule as `allocate`: the owner from any payment, confirmed too, to set a
185
+ * wrong split right; a bot only from one it proposed that is still proposed.
186
186
  */
187
187
  unallocate(input: {
188
188
  payment: string;
@@ -501,8 +501,8 @@ export const financeOperationsOver = (context) => {
501
501
  const row = rowOf(payment, "payment");
502
502
  const ref = `payment:${row.id}`;
503
503
  mayAllocate(row, by);
504
- if (row.review !== "proposed" || row.deleted_at != null)
505
- refuse(`${ref} is ${row.deleted_at != null ? "deleted" : String(row.review)}; only a proposed payment's ` +
504
+ if (row.review === "rejected" || row.deleted_at != null)
505
+ refuse(`${ref} is ${row.deleted_at != null ? "deleted" : "rejected"}; only a proposed or confirmed payment's ` +
506
506
  "allocations are taken back", "finance.unallocate");
507
507
  const target = rowOf(invoice, "invoice");
508
508
  write(database, () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wirecat/cli-core",
3
- "version": "0.571.0",
3
+ "version": "0.573.0",
4
4
  "description": "The messenger-neutral half of a messaging CLI: domain model, message locators, rendering, name resolution, the SQLite seam, the command skeleton and shared read commands, the send guard, run records and the message store",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Viacheslav Ptsarev",